package com.h3c.nem.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eos.common.constant.StatusCodeEnum;
import com.eos.common.custom.BusinessException;
import com.eos.common.util.IdWorker;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.h3c.nem.dto.TbApprovalRecordDTO;
import com.h3c.nem.dto.TbFlowInstDTO;
import com.h3c.nem.dto.TbWorkerDTO;
import com.h3c.nem.dto.enums.TodoTaskNodeEnum;
import com.h3c.nem.dto.form.Attachment;
import com.h3c.nem.dto.form.ConfigTheFormSubmit;
import com.h3c.nem.dto.form.GetFormBusinessData;
import com.h3c.nem.dto.form.HistoryInfo;
import com.h3c.nem.entity.*;
import com.h3c.nem.mapper.*;
import com.h3c.nem.service.CommService;
import com.h3c.nem.service.ISdDeptService;
import com.h3c.nem.service.ITbFlowInstService;
import com.h3c.nem.utils.AppBusinessException;
import com.h3c.nem.utils.BusiEnumDefine;
import com.h3c.nem.utils.CommonUtil;
import com.h3c.nem.utils.InitExampleOrderByUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Copyright (C), 2020-2020, h3c
 * FileName: TbFlowInstServiceImpl
 *
 * @Author: l22886
 * @Date: 2022-01-19
 * Description: tb_flow_inst serviceImpl
 * Version: 1.0
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class TbFlowInstServiceImpl extends ServiceImpl<TbFlowInstMapper, TbFlowInst> implements ITbFlowInstService {

    @Resource
    private TbFlowInstMapper tbFlowInstMapper;

    @Autowired
    private CommService commService;
    @Autowired
    private SdUploadFileMapper sdUploadFileMapper;
    @Autowired
    private TbNewerTaskMapper tbNewerTaskMapper;
    @Autowired
    private TbWorkerMapper tbWorkerMapper;
    @Autowired
    private SdDeptMapper sdDeptMapper;
    @Autowired
    private SdEmailTemplateServiceImpl emailTemplateService;
    @Autowired
    public TbApprovalRecordMapper tbApprovalRecordMapper;
    @Autowired
    private SdTodoTaskServiceImpl todoTaskService;
    @Value("${todotask.pc.url}")
    String todoPcUrl;
    @Value("${sfs.appId}")
    String sfsAppId;
    @Value("${overdueDay}")
    private Integer overdueDay;

    @Resource
    private TbTaskNoteMapper tbTaskNoteMapper;
    @Autowired
    private TbTaskNoteServiceImpl tbTaskNoteService;
    @Autowired
    private SdAllWorkerMapper sdAllWorkerMapper;
    @Autowired
    private SdEmailTemplateMapper sdEmailTemplateMapper;

    @Autowired
    TbFlowInstServiceImpl tbFlowInstService;

    @Resource
    private ISdDeptService deptService;


    private final static long EIGHT_HOUR_TIME = 28800000L;
    private final static int DAY_0 = 0;
    private final static int DAY_7 = 7;
    private final static int DAY_14 = 14;


    /**
     * @title: selectFuzzyByDto
     * @description: 模糊查询操作
     * @params: [ dto ]
     * @return: java.util.List
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    @Override
    public List<TbFlowInstDTO> selectFuzzyByDto(TbFlowInstDTO dto) {
        //List<TbFlowInst> list = tbFlowInstMapper.selectByExample(initFuzzyExample(dto));
        //流程信息
        String loginUserRole = commService.getLoginUserRole();
        String loginUserId = commService.getLoginUserId();
        Boolean isOverDue = dto.getIsOverdue();
        Integer flowStatus = dto.getFlowStatus();
        boolean isAdmin = commService.checkLoginUserRole(BusiEnumDefine.USER_ROLE_ADMIN);
        boolean isBP = commService.checkLoginUserBP();
        boolean isCon = commService.checkLoginUserRole(BusiEnumDefine.USER_ROLE_DEPT_CONTACTOR);
        boolean isMan = commService.checkLoginUserRole(BusiEnumDefine.USER_ROLE_DEPT_MANAGER);
        Set<Integer> authSdDeptIds ;
        if (isBP || isMan) {
            authSdDeptIds = deptService.getAuthDeptIds(isBP, false, isMan, false);
        }else{
            authSdDeptIds = null;
        }

        Date date = null;
        if (isOverDue != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.DAY_OF_MONTH, -overdueDay);
            date = calendar.getTime();
        }

        QueryWrapper<TbFlowInst> tbFlowInstQueryWrapper = new QueryWrapper<>();
        tbFlowInstQueryWrapper.lambda().like(!StringUtils.isEmpty(dto.getFlowName()), TbFlowInst::getFlowName, dto.getFlowName())
                .like(!StringUtils.isEmpty(dto.getWorkerId()), TbFlowInst::getFlowId, dto.getWorkerId())
                .like(!StringUtils.isEmpty(dto.getApprovalUserIds()), TbFlowInst::getApprovalUserIds, dto.getApprovalUserIds())
                //查询所有未结束的
                .ne(flowStatus == null, TbFlowInst::getFlowStatus, BusiEnumDefine.flowStatusFinished)
                .eq(flowStatus != null, TbFlowInst::getFlowStatus, flowStatus)
                //是否超期
                .ge(isOverDue != null && isOverDue, TbFlowInst::getArriveTime, date)
                .le(isOverDue != null && !isOverDue, TbFlowInst::getArriveTime, date)
                //按权限查询
                .and(e -> e.in(isBP, TbFlowInst::getWorkerDeptId, authSdDeptIds)
                        .or(isBP)
                        .inSql(isCon,TbFlowInst::getWorkerId,"select worker_id from tb_worker where dept_contactor like '%" + loginUserId +"%'"));
        List<TbFlowInst> list = tbFlowInstMapper.selectList(tbFlowInstQueryWrapper);

        //员工信息
        List<String> workIds = list.stream().map(TbFlowInst::getWorkerId).collect(Collectors.toList());
        List<TbWorker> tbWorkers = workIds.size() > 0 ? tbWorkerMapper.selectBatchIds(workIds) : new ArrayList<>();
        Map<String, String> approvers = tbWorkers.stream().collect(Collectors.toMap(o -> o.getWorkerId(), o -> {
            return (StringUtils.isEmpty(o.getFirstApprover()) ? "" : "第一考核人/")
                    + (StringUtils.isEmpty(o.getSecondApprover()) ? "" : "第二考核人/")
                    + (StringUtils.isEmpty(o.getThirdApprover()) ? "" : "第三考核人/")
                    + (StringUtils.isEmpty(o.getFinalApprover()) ? "" : "最终考核人/")
                    + (StringUtils.isEmpty(o.getFinalJudger()) ? "" : "最终决策人");
        }));

        //返回DTOList
        List<TbFlowInstDTO> tbFlowInstDTOS = JSONArray.parseArray(JSONArray.toJSONString(list), TbFlowInstDTO.class);
        tbFlowInstDTOS.forEach(tbFlowInstDTO -> {
            if (!StringUtils.isEmpty(tbFlowInstDTO.getApprovalUserIds())) {
                //获取处理人姓名
                SdAllWorker sdAllWorker = commService.getAllWorkerDoFromLocalCache(tbFlowInstDTO.getApprovalUserIds());
                if (sdAllWorker != null) {
                    tbFlowInstDTO.setApprovalUserNames(sdAllWorker.getWorkerName());
                }
            }
            String allApprovalNames = approvers.get(tbFlowInstDTO.getWorkerId());
            if (!StringUtils.isEmpty(allApprovalNames)) {
                if (!BusiEnumDefine.flowCodeTurnFormalCheck.equals(tbFlowInstDTO.getFlowCode())) {
                    allApprovalNames = allApprovalNames.replaceAll("最终决策人", "");
                }
                if (BusiEnumDefine.flowCodeTurnFormalPlan.equals(tbFlowInstDTO.getFlowCode())) {
                    allApprovalNames = "转正计划填写/" + allApprovalNames;
                }
                if (BusiEnumDefine.flowCodeMonthlyPromise.equals(tbFlowInstDTO.getFlowCode())) {
                    allApprovalNames = "月度承诺填写/" + allApprovalNames;
                }
                tbFlowInstDTO.setAllApprovalNames(allApprovalNames);
            }

            Integer days = getDaysToNow(System.currentTimeMillis(), tbFlowInstDTO.getArriveTime().getTime());
            tbFlowInstDTO.setArriveDays(days);
            tbFlowInstDTO.setArriveTimeFormat(tbFlowInstDTO.getArriveTime());
            tbFlowInstDTO.setCreateTimeFormat(tbFlowInstDTO.getCreateTime());
        });
        return tbFlowInstDTOS;
    }

    /**
     * @title: selectFuzzyByDto
     * @description: 模糊查询操作
     * @params: [ dto ]
     * @return: java.util.List
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    @Override
    public PageInfo<TbFlowInstDTO> selectFuzzyByDtoPage(TbFlowInstDTO dto, Integer currentPage, Integer pageSize) {
        //List<TbFlowInst> list = tbFlowInstMapper.selectByExample(initFuzzyExample(dto));
        //流程信息

        String loginUserRole = commService.getLoginUserRole();
        String loginUserId = commService.getLoginUserId();
        Boolean isOverDue = dto.getIsOverdue();
        Boolean jobLevel = dto.getJobLevel();
        Integer flowStatus = dto.getFlowStatus();
        boolean isAdmin = commService.checkLoginUserRole(BusiEnumDefine.USER_ROLE_ADMIN);
        boolean isCon = commService.checkLoginUserRole(BusiEnumDefine.USER_ROLE_DEPT_CONTACTOR);
        boolean isBP = commService.checkLoginUserBP();
        boolean isMan = commService.checkLoginUserRole(BusiEnumDefine.USER_ROLE_DEPT_MANAGER);
        Set<Integer> authSdDeptIds;
        if (isBP || isMan) {
            authSdDeptIds = deptService.getAuthDeptIds(isBP, false, isMan, false);
        }else{
            authSdDeptIds = null;
        }

        Date date = null;
        if (isOverDue != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.set(Calendar.HOUR, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.add(Calendar.DAY_OF_MONTH, -overdueDay);
            date = calendar.getTime();
        }

        List<Integer> flowStatuses = new ArrayList<>();

        flowStatuses.add(BusiEnumDefine.flowStatusFinished);
        flowStatuses.add(BusiEnumDefine.flowStatusTermination);


        QueryWrapper<TbFlowInst> tbFlowInstQueryWrapper = new QueryWrapper<>();
        tbFlowInstQueryWrapper.lambda().like(!StringUtils.isEmpty(dto.getFlowName()), TbFlowInst::getFlowName, dto.getFlowName())
                .eq(!StringUtils.isEmpty(dto.getWorkerId()), TbFlowInst::getWorkerId, dto.getWorkerId())
                .like(!StringUtils.isEmpty(dto.getApprovalUserIds()), TbFlowInst::getApprovalUserIds, dto.getApprovalUserIds())
                //查询所有未结束的
                .notIn(flowStatus == null, TbFlowInst::getFlowStatus, flowStatuses)
                //查询终止及完成
                .in(flowStatus != null, TbFlowInst::getFlowStatus, flowStatuses)
                //是否超期
                .le(isOverDue != null && isOverDue, TbFlowInst::getArriveTime, date)
                .ge(isOverDue != null && !isOverDue, TbFlowInst::getArriveTime, date)
                //按权限查询
                .and(!isAdmin,e-> e.in(isBP || isMan, TbFlowInst::getWorkerDeptId, authSdDeptIds)
                        .or(isCon)
                        .inSql(isCon,TbFlowInst::getWorkerId,"select worker_id from tb_worker where dept_contactor like '%" + loginUserId +"%'"))
                .inSql(jobLevel!=null&&jobLevel,TbFlowInst::getWorkerId,"select worker_id from tb_worker where job_level >= 18")
                .inSql(jobLevel!=null&&!jobLevel,TbFlowInst::getWorkerId,"select worker_id from tb_worker where job_level < 18");

        //分页
        Page page = PageHelper.startPage(currentPage, pageSize);//todo 为什么这里之后其他地方的查询分页不生效？
        List<TbFlowInst> list = tbFlowInstMapper.selectList(tbFlowInstQueryWrapper);

        //员工信息
        List<String> workIds = list.stream().map(TbFlowInst::getWorkerId).collect(Collectors.toSet()).stream().collect(Collectors.toList());
        List<TbWorker> tbWorkers = workIds.size() > 0 ? tbWorkerMapper.selectBatchIds(workIds) : new ArrayList<>();
        Map<String, String> approvers = tbWorkers.stream().collect(Collectors.toMap(o -> o.getWorkerId(), o -> {
            return (StringUtils.isEmpty(o.getFirstApprover()) ? "" : "第一考核人/")
                    + (StringUtils.isEmpty(o.getSecondApprover()) ? "" : "第二考核人/")
                    + (StringUtils.isEmpty(o.getThirdApprover()) ? "" : "第三考核人/")
                    + (StringUtils.isEmpty(o.getFinalApprover()) ? "" : "最终考核人/")
                    + (StringUtils.isEmpty(o.getFinalJudger()) ? "" : "最终决策人");
        }));

        long currentTimeMillis = System.currentTimeMillis();

        List<TbFlowInstDTO> tbFlowInstDTOList1 = new ArrayList<>();
        List<TbFlowInstDTO> tbFlowInstDTOList2 = new ArrayList<>();
        //返回DTOList
        List<TbFlowInstDTO> tbFlowInstDTOS = JSONArray.parseArray(JSONArray.toJSONString(list), TbFlowInstDTO.class);
        tbFlowInstDTOS.forEach(tbFlowInstDTO -> {
            if (!StringUtils.isEmpty(tbFlowInstDTO.getApprovalUserIds())) {
                //获取处理人姓名
                SdAllWorker sdAllWorker = commService.getAllWorkerDoFromLocalCache(tbFlowInstDTO.getApprovalUserIds());
                if (sdAllWorker != null) {
                    tbFlowInstDTO.setApprovalUserNames(sdAllWorker.getWorkerName());
                }
            }
            String allApprovalNames = approvers.get(tbFlowInstDTO.getWorkerId());
            if (!StringUtils.isEmpty(allApprovalNames)) {
                if (!BusiEnumDefine.flowCodeTurnFormalCheck.equals(tbFlowInstDTO.getFlowCode())) {
                    allApprovalNames = allApprovalNames.replaceAll("最终决策人", "");
                }
                if (BusiEnumDefine.flowCodeTurnFormalPlan.equals(tbFlowInstDTO.getFlowCode())) {
                    allApprovalNames = "转正计划填写/" + allApprovalNames;
                }
                if (BusiEnumDefine.flowCodeMonthlyPromise.equals(tbFlowInstDTO.getFlowCode())) {
                    allApprovalNames = "月度承诺填写/" + allApprovalNames;
                }
                tbFlowInstDTO.setAllApprovalNames(allApprovalNames);
            }

            Integer days = getDaysToNow(currentTimeMillis, tbFlowInstDTO.getArriveTime().getTime());
            tbFlowInstDTO.setArriveDays(days);
            Integer totalDays = getDaysToNow(currentTimeMillis, tbFlowInstDTO.getCreateTime().getTime());
            tbFlowInstDTO.setTotalDays(totalDays);
            tbFlowInstDTO.setArriveTimeFormat(tbFlowInstDTO.getArriveTime());
            tbFlowInstDTO.setCreateTimeFormat(tbFlowInstDTO.getCreateTime());

            Map<String,Object> map = CommService.dataCacheMap;
            if(!ObjectUtils.isEmpty(map.get("allWorker"+tbFlowInstDTO.getWorkerId()))){
                tbFlowInstDTO.setIsResign(1);//离职
                tbFlowInstDTOList1.add(tbFlowInstDTO);
            }else{
                tbFlowInstDTO.setIsResign(2);
                tbFlowInstDTOList2.add(tbFlowInstDTO);
            }
        });
        PageInfo<TbFlowInstDTO> pageInfo = page.toPageInfo();
        if(!StringUtils.isEmpty(dto.getIsResign())&&dto.getIsResign()==1) {
            pageInfo.setList(tbFlowInstDTOList1);
        }else if(!StringUtils.isEmpty(dto.getIsResign())&&dto.getIsResign()==2){
            pageInfo.setList(tbFlowInstDTOList2);
        }else {
            pageInfo.setList(tbFlowInstDTOS);
        }
        return pageInfo;
    }

    /**
     * @title: selectByDto
     * @description: 精确查询操作
     * @params: [ dto ]
     * @return: java.util.List
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    @Override
    public List<TbFlowInstDTO> selectByDto(TbFlowInstDTO dto) {
        //List<TbFlowInst> list = tbFlowInstMapper.selectByExample(initExample(dto));
        List<TbFlowInst> list = tbFlowInstMapper.queryList(JSONObject.parseObject(JSONObject.toJSONString(dto), TbFlowInst.class));
        return JSONArray.parseArray(JSONArray.toJSONString(list), TbFlowInstDTO.class);
    }

    /**
     * @title: insertDto
     * @description: 插入操作
     * @params: [ dto ]
     * @return: Integer
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    @Override
    public Integer insertDto(TbFlowInstDTO dto) {
        //if (null == dto.getId() || "".equals(dto.getId())) {
        //    String pkId = IdWorker.nextId() + "";
        //    dto.setId(pkId);
        //}
        return tbFlowInstMapper.insertTbFlowInst(JSONObject.parseObject(JSON.toJSONString(dto), TbFlowInst.class));
    }

    @Override
    public Boolean insertBatch(List<TbFlowInst> list) {
        return saveBatch(list);
    }

    /**
     * 精准查询某个任务
     *
     * @param dto taskDto
     * @return dto
     */
    @Override
    public Map<String, Object> queryTaskByDto(TbFlowInstDTO dto) {
        Map<String, Object> result = new HashMap<>();

        //获取审批记录
        TbFlowInst flowInst = tbFlowInstMapper.selectById(dto.getFlowId());
        if (flowInst == null) {
            return null;
        }
        TbTaskNote taskNote = tbTaskNoteMapper.selectById(dto.getFlowId());
        String taskNoteStr = taskNote == null ? "" : new String(taskNote.getTaskNote(), StandardCharsets.UTF_8);
        TbFlowInstDTO flowInstDTO = JSONObject.parseObject(JSON.toJSONString(flowInst), TbFlowInstDTO.class);
        flowInstDTO.setTaskFinishNote(taskNoteStr);
        result.put("flowInst", flowInstDTO);

        //获取任务信息
        String taskId = flowInst.getFlowNote();
        TbNewerTask task = tbNewerTaskMapper.selectById(taskId);
        if (task == null) {
            return null;
        }
        result.put("newerTask", task);

        QueryWrapper<TbApprovalRecord> approvalQW = new QueryWrapper<>();
        approvalQW.lambda().eq(TbApprovalRecord::getFlowId, flowInst.getFlowId())
                .orderByDesc(TbApprovalRecord::getFlowArriveTime);
        List<TbApprovalRecordDTO> approvalRecords = tbApprovalRecordMapper.queryListAndFile(flowInst);
        result.put("approvalRecord", approvalRecords);

        QueryWrapper<SdUploadFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SdUploadFile::getBusiId, flowInst.getFlowId());
        List<SdUploadFile> uploadFiles = sdUploadFileMapper.selectList(queryWrapper);
        result.put("fileList", uploadFiles);

        QueryWrapper<SdUploadFile> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SdUploadFile::getBusiId, flowInst.getFlowNote());
        List<SdUploadFile> uploadFiles2 = sdUploadFileMapper.selectList(queryWrapper2);
        result.put("taskFileList", uploadFiles2);

        return result;
    }

    /**
     * 通过busiId获取数据
     *
     * @param busiType
     * @param busiId
     * @return
     */
    @Override
    public List<Attachment> getFileListByBusiId(Integer busiType, String busiId) {
        List<Attachment> list = new ArrayList<>();
        QueryWrapper<SdUploadFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SdUploadFile::getBusiId, busiId).eq(SdUploadFile::getBusiType, busiType);
        List<SdUploadFile> uploadFiles = sdUploadFileMapper.selectList(queryWrapper);
        uploadFiles.forEach(file -> {
            Attachment attachment = new Attachment();
            attachment.setFileId(file.getFileId());
            attachment.setFileName(file.getFileName());
            attachment.setFileAppId(sfsAppId);
            list.add(attachment);
        });
        return list;
    }

    public List<HistoryInfo> getHistoryInfosForPre(String docId) {
        LambdaQueryWrapper<TbApprovalRecord> approvalWrapper = new LambdaQueryWrapper<>();
        approvalWrapper.eq(TbApprovalRecord::getFlowId, docId)
                .orderByDesc(TbApprovalRecord::getApprovalTime);
        List<TbApprovalRecord> approvalRecords = tbApprovalRecordMapper.selectList(approvalWrapper);
        List<String> userIds = approvalRecords.stream()
                .map(TbApprovalRecord::getApprovalUserId).collect(Collectors.toList());
        if (userIds.isEmpty()) {
            return new ArrayList<>();
        }
        QueryWrapper<SdAllWorker> allWorkerQW = new QueryWrapper<>();
        allWorkerQW.lambda().in(SdAllWorker::getWorkerId, userIds);
        List<SdAllWorker> allWorkers = sdAllWorkerMapper.selectList(allWorkerQW);
        Map<String, SdAllWorker> domainAccountMap = allWorkers.stream()
                .collect(Collectors.toMap(SdAllWorker::getWorkerId, o -> o));

        List<HistoryInfo> mapList = new ArrayList<>();

        approvalRecords.forEach(record -> {
            //流转人信息
            SdAllWorker allWorker = domainAccountMap.get(record.getApprovalUserId());
            JSONObject approver = new JSONObject();
            if (allWorker != null) {
                approver.put("empNumber", allWorker.getDomainAccount());
                approver.put("name", allWorker.getWorkerName());
            }

            //流转信息
            HistoryInfo historyInfo = new HistoryInfo();
            historyInfo.setApprover(approver);
            if (Objects.equals(record.getApprovalType(), BusiEnumDefine.APPROVAL_TYPE_TRANSFER)) {
                historyInfo.setApproveType("Transfer");
                historyInfo.setApproveTypeVal("转发");
            } else {
                if (Objects.equals(record.getApprovalResult(), BusiEnumDefine.APPROVAL_BACKUP)) {
                    historyInfo.setApproveType("Reject");
                    historyInfo.setApproveTypeVal("拒绝");
                } else {
                    historyInfo.setApproveType("Agree");
                    historyInfo.setApproveTypeVal("同意");
                }
            }
            TodoTaskNodeEnum enumByValue = TodoTaskNodeEnum.getEnumByValue(record.getApprovalType());
            historyInfo.setCurrentNode(enumByValue.getName());
            historyInfo.setApproveTime(record.getApprovalTime());
            historyInfo.setApproveOpinion(CommonUtil.null2Empty(record.getApprovalNote()));
            mapList.add(historyInfo);
        });
        return mapList;
    }

    /**
     * 构建表单 historyInfos 部分数据
     */
    @Override
    public List<HistoryInfo> getHistoryInfos(String flowId) {

        TbFlowInst tbFlowInst = tbFlowInstMapper.selectById(flowId);
        String workerId = tbFlowInst.getWorkerId();
        TbWorker tbWorker = tbWorkerMapper.selectById(workerId);
        String dataSrc = tbWorker.getDataSrc();

        //流转记录
        QueryWrapper<TbApprovalRecord> approvalQW = new QueryWrapper<>();
        approvalQW.lambda().eq(TbApprovalRecord::getFlowId, flowId)
                .orderByDesc(TbApprovalRecord::getApprovalTime);
        List<TbApprovalRecord> approvalRecords = tbApprovalRecordMapper.selectList(approvalQW);
        List<String> userIds = approvalRecords.stream()
                .map(TbApprovalRecord::getApprovalUserId).collect(Collectors.toList());
        if (userIds.isEmpty()) {
            return new ArrayList<>();
        }

        //用户信息 approvalUserId
        QueryWrapper<SdAllWorker> allWorkerQW = new QueryWrapper<>();
        allWorkerQW.lambda().in(SdAllWorker::getWorkerId, userIds);
        List<SdAllWorker> allWorkers = sdAllWorkerMapper.selectList(allWorkerQW);
        Map<String, SdAllWorker> domainAccountMap = allWorkers.stream()
                .collect(Collectors.toMap(SdAllWorker::getWorkerId, o -> o));

        List<HistoryInfo> mapList = new ArrayList<>();
        approvalRecords.forEach(record -> {

            //流转人信息
            SdAllWorker allWorker = domainAccountMap.get(record.getApprovalUserId());
            JSONObject approver = new JSONObject();
            if (allWorker != null) {
                approver.put("empNumber", allWorker.getDomainAccount());
                approver.put("name", allWorker.getWorkerName());
            }

            //流转信息
            HistoryInfo historyInfo = new HistoryInfo();
            historyInfo.setApprover(approver);
            if (Objects.equals(record.getApprovalType(), BusiEnumDefine.APPROVAL_TYPE_TRANSFER)) {
                historyInfo.setApproveType("Transfer");
                historyInfo.setApproveTypeVal("转发");
            } else {
                if (Objects.equals(record.getApprovalResult(), BusiEnumDefine.APPROVAL_BACKUP)) {
                    historyInfo.setApproveType("Reject");
                    historyInfo.setApproveTypeVal("拒绝");
                } else {
                    historyInfo.setApproveType("Agree");
                    historyInfo.setApproveTypeVal("同意");
                }
            }
            TodoTaskNodeEnum enumByValue = TodoTaskNodeEnum.getEnumByValue(record.getApprovalType());
            historyInfo.setCurrentNode(enumByValue.getName());
            historyInfo.setApproveTime(record.getApprovalTime());
            String score = "";
            if (record.getApprovalType() == BusiEnumDefine.APPROVAL_TYPE_MONTHLY_PROMISE_CHECK && !StringUtils.isEmpty(record.getApprovalScore())) {
                score = "考核评价：" + record.getApprovalScore() + " 评价说明：";
            }
            if (!StringUtils.isEmpty(dataSrc)&&"应届毕业生".equals(dataSrc)&&record.getApprovalType() == BusiEnumDefine.APPROVAL_TYPE_TURN_FORMAL_CHECK && !StringUtils.isEmpty(record.getApprovalScore())) {
                String appRes = record.getApprovalResult().equals(BusiEnumDefine.APPROVAL_APPROVE)?"通过":"不通过";
                score = "考核成绩：" + CommonUtil.null2Empty(record.getApprovalScore()) +"  "+"考核结果:"+appRes+ "  "+"评价说明：";
            }
            historyInfo.setApproveOpinion(score + CommonUtil.null2Empty(record.getApprovalNote()));
            mapList.add(historyInfo);
        });
        return mapList;
    }

    /**
     * 构建 Data 部分数据
     */
    @Override
    public Map<String, Object> getTaskInfoData(GetFormBusinessData formBusinessData) {
        String flowId = formBusinessData.getDocId();
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        TbFlowInst flowInst = tbFlowInstMapper.selectById(flowId);
        if (flowInst == null) {
            log.error("FlowInst数据缺失");
            throw new BusinessException(StatusCodeEnum.SEARCH_FAIl);
        }

        //获取小任务信息
        String taskId = flowInst.getFlowNote();
        TbNewerTask task = tbNewerTaskMapper.selectById(taskId);
        if (task == null) {
            log.error("NewerTask数据缺失");
            throw new BusinessException(StatusCodeEnum.SEARCH_FAIl);
        }
        data.put("taskName", task.getTaskName());
        data.put("taskNote", task.getTaskNote());

        //提交信息
        TbTaskNote taskNote = tbTaskNoteMapper.selectById(flowId);
        String taskNoteStr = taskNote == null ? "" : new String(taskNote.getTaskNote(), StandardCharsets.UTF_8);
        TbFlowInstDTO flowInstDTO = JSONObject.parseObject(JSON.toJSONString(flowInst), TbFlowInstDTO.class);
        flowInstDTO.setTaskFinishNote(taskNoteStr);
        data.put("taskFinishNote", taskNoteStr);
        //附件
        List<Attachment> attachments = getFileListByBusiId(1, flowInst.getFlowId());
        data.put("file1", attachments);

        result.put("data", data);

        //historyInfos
        List<HistoryInfo> historyInfos = getHistoryInfos(flowInst.getFlowId());
        result.put("historyInfos", historyInfos);

        //当前处理人
        String approvalUserIds = flowInstDTO.getApprovalUserIds();
        String[] ids = approvalUserIds.split(",");
        QueryWrapper<SdAllWorker> allWorkerQW = new QueryWrapper<>();
        allWorkerQW.lambda().in(SdAllWorker::getWorkerId, Arrays.asList(ids));
        List<SdAllWorker> allWorker = sdAllWorkerMapper.selectList(allWorkerQW);
        String accountStr = allWorker.stream().map(SdAllWorker::getDomainAccount).collect(Collectors.joining(","));
        result.put("currentEmpNumber", accountStr);

        return result;
    }

    /**
     * 员工提交任务
     *
     * @param flowId
     * @param taskFinishNote
     * @param type
     * @return
     */
    @Override
    @Transactional
    public Integer submitTask(String flowId, String taskFinishNote, String type) {

        TbTaskNote tbTaskNote = new TbTaskNote();
        tbTaskNote.setFlowId(flowId);
        tbTaskNote.setTaskNote(taskFinishNote.getBytes(StandardCharsets.UTF_8));

        //员工小任务信息
        TbFlowInst flowInst = tbFlowInstMapper.selectById(flowId);
        String workerId = flowInst.getWorkerId();
        String workerName = flowInst.getWorkerName();

        //校验
        String loginUserId = commService.getLoginUserId();
        if (!loginUserId.equals(workerId)) {
            throw new BusinessException(StatusCodeEnum.UN_AUTH.getCode(), "没有操作权限");
        }

        if (type.equals("0")) {
            //保存草稿 直接退出
            return tbTaskNoteService.saveOrUpdate(tbTaskNote) ? 1 : 0;
        }

        //任务信息
        TbNewerTask tbNewerTask = tbNewerTaskMapper.selectById(flowInst.getFlowNote());
        Integer approverType = tbNewerTask.getApproverType();
        //员工信息
        TbWorker tbWorker = tbWorkerMapper.selectById(workerId);

        //记录日志
        TbApprovalRecord approvalRecord = new TbApprovalRecord();
        approvalRecord.setApprovalId(IdWorker.nextId() + "");
        approvalRecord.setFlowId(flowId);
        approvalRecord.setFlowArriveTime(new Date());
        approvalRecord.setApprovalType(BusiEnumDefine.FLOW_STATUS_EXECUTE_TASK);
        approvalRecord.setApprovalUserId(workerId);
        approvalRecord.setApprovalNote("提交小任务");
        approvalRecord.setApprovalResult(1); //通过
        approvalRecord.setApprovalUserInfo(workerId + "/" + workerName);
        approvalRecord.setApprovalTime(new Date());
        tbApprovalRecordMapper.insert(approvalRecord);

        //确定审核人
        String userId;
        if (BusiEnumDefine.TASK_APPROVAL_TEACHER == approverType) {
            userId = tbWorker.getTeacherInfo().split("/")[1];
        } else if (BusiEnumDefine.TASK_APPROVAL_DEPT_MANAGER == approverType) {
            userId = tbWorker.getDirectManager().split("/")[1];
        } else {
            Integer deptId = tbWorker.getDirectDeptId();
            SdDept sdDept = sdDeptMapper.selectById(deptId);
            if (BusiEnumDefine.TASK_APPROVAL_CONTACTOR == approverType) {
                userId = sdDept.getContactorId();
            } else if (BusiEnumDefine.TASK_APPROVAL_BP == approverType) {
                userId = sdDept.getBpUserId();
            } else if (BusiEnumDefine.TASK_APPROVAL_OTHER == approverType) {
                userId = tbNewerTask.getApproverId();
            } else {
                throw new BusinessException(StatusCodeEnum.ADD_FAIl.getCode(), "不存在的小任务审核人类型");
            }
        }
        String approvedUserIds = flowInst.getApprovedUserIds();
        //历史处理人为空，或者历史处理人不包含当前员工，准备插入数据
        if (StringUtils.isEmpty(approvedUserIds) || !approvedUserIds.contains(flowInst.getApprovalUserIds())) {
            //初始人
            String basicUser = StringUtils.isEmpty(approvedUserIds) ? "" : approvedUserIds + ",";
            flowInst.setApprovedUserIds(basicUser + flowInst.getApprovalUserIds());
        }
        flowInst.setApprovalUserIds(userId);
        //更新状态
        flowInst.setFlowStatus(BusiEnumDefine.FLOW_STATUS_CHECK_TASK);
        flowInst.setCurrentStage("审核小任务");
        int update = tbFlowInstMapper.updateById(flowInst);
        tbTaskNoteService.saveOrUpdate(tbTaskNote);

        SdEmailTemplate taskEmail = sdEmailTemplateMapper.selectById(BusiEnumDefine.TASK_FINISH_SUBMIT);

        //发邮件 员工提交后给审核人发送邮件
        SdAllWorker allWorker = commService.getAllWorkerDoFromLocalCache(userId);
        sendEmail(allWorker, flowId, workerId, taskEmail);

        todoTaskService.initOrUpdateTodoTask(flowInst);
        return update;
    }

    /**
     * 发送邮件
     *
     * @param worker      发送对象
     * @param flowId      流程
     * @param applyUserId 发送人
     * @param taskEmail   邮件内容
     */
    private void sendEmail(SdAllWorker worker, String flowId, String applyUserId, SdEmailTemplate taskEmail) {

        String title = taskEmail.getEmailTemplateTitle();
        String content = taskEmail.getEmailTemplateContent();

        SdNoticeRecord sdNoticeRecord = new SdNoticeRecord();
        sdNoticeRecord.setNoticeId(IdWorker.nextId() + "");
        sdNoticeRecord.setFlowId(flowId);
        sdNoticeRecord.setApplyUserId(applyUserId);
        sdNoticeRecord.setNoticeType(BusiEnumDefine.NOTICE_TYPE_EMAIL);
        sdNoticeRecord.setTargetId(worker.getWorkerId());
        sdNoticeRecord.setTargetName(worker.getWorkerName());
        sdNoticeRecord.setTargetEmail(worker.getEmail());
        sdNoticeRecord.setNoticeTitle(title);
        sdNoticeRecord.setNoticeContent(content);
        sdNoticeRecord.setCreateTime(new Date());
        commService.sendMessage(sdNoticeRecord);
    }

    /**
     * @title: updateDto
     * @description: 修改操作
     * @params: [ dto ]
     * @return: Integer
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    @Override
    public Integer updateDto(TbFlowInstDTO dto) {
        //if (null != dto && null != dto.getId() && !"".equals(dto.getId())) {
        return tbFlowInstMapper.updateTbFlowInst(JSONObject.parseObject(JSON.toJSONString(dto), TbFlowInst.class));
        //return tbFlowInstMapper.updateByPrimaryKey(JSONObject.parseObject(JSON.toJSONString(dto), TbFlowInst.class));
        //} else {
        //    return 0;
        //}
    }

    /**
     * @title: deleteDto
     * @description: 删除操作
     * @params: [ dto ]
     * @return: Integer
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    @Override
    public Integer deleteDto(TbFlowInstDTO dto) {
        //if (null != dto && null != dto.getId() && !"".equals(dto.getId())) {
        return tbFlowInstMapper.deleteTbFlowInst(JSONObject.parseObject(JSON.toJSONString(dto), TbFlowInst.class));
        //return tbFlowInstMapper.deleteByPrimaryKey(dto.getId());
        //} else {
        //    return 0;
        //}
    }


    //新建流程
    public Boolean creatFlowInst(TbFlowInstDTO dto) {
        dto.setFlowId(IdWorker.nextId() + "");
        dto.setCreateTime(new Date());
        dto.setArriveTime(new Date());
        Integer result = tbFlowInstMapper.insertTbFlowInst(JSONObject.parseObject(JSONObject.toJSONString(dto), TbFlowInst.class));
        return true;
    }

    //更新流程
    public Boolean updateFlowInst(TbFlowInstDTO dto) {
        dto.setArriveTime(new Date());
//        Integer result = tbFlowInstMapper.updateTbFlowInst(JSONObject.parseObject(JSONObject.toJSONString(dto), TbFlowInst.class));
        tbFlowInstMapper.updateById(JSONObject.parseObject(JSONObject.toJSONString(dto), TbFlowInst.class));
        return true;
    }


    //创建具体流程
    @Override
    public Boolean createSpecificFlowInst(TbWorkerDTO workerDTO, Set<String> flowWorkerIdCodeSet) {
        String workerId = workerDTO.getWorkerId();
        String workerName = workerDTO.getWorkerName();
        Date joinDate = workerDTO.getJoinDate();
        int joinMonths = getJoinMonths(joinDate);

        if (joinMonths < 0) {
            return false;
//            throw new AppBusinessException("入职时间早于当前时间");
        }

        List<TbFlowInstDTO> tbFlowInstDTOS = createAllExpireSpecificFlowInst(workerDTO,flowWorkerIdCodeSet);
        TbFlowInstDTO flowInstDTO = setSpecificFlowInst(workerDTO);
        if (!StringUtils.isEmpty(flowInstDTO.getFlowCode())) {
            tbFlowInstDTOS.add(flowInstDTO);
        }
        tbFlowInstDTOS.forEach(tbFlowInstDTO -> {
            creatFlowInst(tbFlowInstDTO);
//            setApprovalRecord(flowInstDTO, BusiEnumDefine, "");
            //创建待办
            todoTaskService.initOrUpdateTodoTask(tbFlowInstDTO);
            //发邮件 待处理人发送邮件
            sendMail(tbFlowInstDTO);
        });
        return true;
    }

    //更新具体流程到下个状态
    public int forwardSpecificFlowInst(TbWorkerDTO workerDTO, TbFlowInstDTO flowInstDTO) {
        log.info(" forwardSpecificFlowInst workerDTO: " + workerDTO);
        log.info(" forwardSpecificFlowInst flowInstDTO: " + flowInstDTO);
        Integer flowStatus = flowInstDTO.getFlowStatus();
        String approvalUserIds = flowInstDTO.getApprovalUserIds();
        TbFlowInstDTO toFlowInstDTO = new TbFlowInstDTO();
        BeanUtils.copyProperties(flowInstDTO, toFlowInstDTO);

        String nextApprovalId = getNextApproverId(workerDTO, flowInstDTO, approvalUserIds);
        log.info("~~~~~~~~~~~~~~~~~~~~~~~~~ " + nextApprovalId);
        StringBuilder approvedUserIds = new StringBuilder();
        if (!StringUtils.isEmpty(flowInstDTO.getApprovedUserIds())) {
            approvedUserIds.append(flowInstDTO.getApprovedUserIds());
        }
        if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromise) {
            toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromiseExamine);
            toFlowInstDTO.setApprovalUserIds(nextApprovalId);
        } else if (flowStatus == BusiEnumDefine.flowStatusTurnFormalPlan) {
            toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalExamine);
            toFlowInstDTO.setApprovalUserIds(nextApprovalId);
        } else if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromiseExamine || flowStatus == BusiEnumDefine.flowStatusMonthlyPromiseCheck
                || flowStatus == BusiEnumDefine.flowStatusTurnFormalExamine || flowStatus == BusiEnumDefine.flowStatusTurnFormalCheck) {
            if (StringUtils.isEmpty(nextApprovalId)) {
                toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusFinished);
                toFlowInstDTO.setApprovalUserIds("");
            } else {
                toFlowInstDTO.setApprovalUserIds(nextApprovalId);
            }
        }
        approvedUserIds.append(approvalUserIds + ",");
        toFlowInstDTO.setApprovedUserIds(approvedUserIds.toString());
        updateSpecificFlowInst(workerDTO, flowInstDTO, toFlowInstDTO);
        //具体业务去处理审批记录，这里不再处理

        //创建待办
        todoTaskService.initOrUpdateTodoTask(toFlowInstDTO);
        //发邮件 待处理人发送邮件
        if (!StringUtils.isEmpty(toFlowInstDTO.getApprovalUserIds())) {
            sendMail(toFlowInstDTO);
        }
        if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusFinished)) {
            return BusiEnumDefine.flowStatusFinished;
        }
        return 0;
    }

    /**
     * 获取下一个审批人工号， 已审批过则跳过
     * 当前审批人等于被审批人， 返回第一个考核人工号
     * 当前审批人为最后一个考核人工号，返回 ""
     * 其他获取下一个考核人工号
     */
    public String getNextApproverId(TbWorkerDTO workerDTO, TbFlowInstDTO flowInstDTO, String thisApprover) {

        String firstApprover = workerDTO.getFirstApprover();
        String secondApprover = workerDTO.getSecondApprover();
        String thirdApprover = workerDTO.getThirdApprover();
        String finalApprover = workerDTO.getFinalApprover();
        String finalJudger = workerDTO.getFinalJudger();
        String workerId = workerDTO.getWorkerId();

        String firstApproverId = StringUtils.isEmpty(firstApprover) ? "" : firstApprover.split("/")[1];
        String secondApproverId = StringUtils.isEmpty(secondApprover) ? "" : secondApprover.split("/")[1];
        String thirdApproverId = StringUtils.isEmpty(thirdApprover) ? "" : thirdApprover.split("/")[1];
        String finalApproverId = StringUtils.isEmpty(finalApprover) ? "" : finalApprover.split("/")[1];
        String finalJudgerId = StringUtils.isEmpty(finalJudger) ? "" : finalJudger.split("/")[1];


        String approvedUserIds = flowInstDTO.getApprovedUserIds();
        String flowCode = flowInstDTO.getFlowCode();
        List<String> allApproverIdList = new ArrayList<>();
        //没有审批过的考核人
        List<String> approverIdList = new ArrayList<>();

        if (!StringUtils.isEmpty(firstApproverId)) {
            if ((StringUtils.isEmpty(approvedUserIds) || approvedUserIds.indexOf(firstApproverId) < 0)) {
                approverIdList.add(firstApproverId);
            }

            allApproverIdList.add(firstApproverId);
        }
        if (!StringUtils.isEmpty(secondApproverId)) {
            if ((StringUtils.isEmpty(approvedUserIds) || approvedUserIds.indexOf(secondApproverId) < 0)) {
                approverIdList.add(secondApproverId);
            }
            allApproverIdList.add(secondApproverId);

        }
        if (!StringUtils.isEmpty(thirdApproverId)) {
            if ((StringUtils.isEmpty(approvedUserIds) || approvedUserIds.indexOf(thirdApproverId) < 0)) {
                approverIdList.add(thirdApproverId);
            }
            allApproverIdList.add(thirdApproverId);

        }
        if (!StringUtils.isEmpty(finalApproverId)) {
            if ((StringUtils.isEmpty(approvedUserIds) || approvedUserIds.indexOf(finalApproverId) < 0)) {
                approverIdList.add(finalApproverId);
            }
            allApproverIdList.add(finalApproverId);

        }
        if (!StringUtils.isEmpty(finalJudgerId) && flowCode.equals(BusiEnumDefine.flowCodeTurnFormalCheck)) {
            if ((StringUtils.isEmpty(approvedUserIds) || approvedUserIds.indexOf(finalJudgerId) < 0)) {
                approverIdList.add(finalJudgerId);
            }
            allApproverIdList.add(finalJudgerId);

        }
        //若是转办人（当前处理人不在所有配置的审批人中），则替换成在WorkerDTO中存在的的审批人
        if (!StringUtils.isEmpty(approvedUserIds) && CommonUtil.contactListStrings(allApproverIdList).indexOf(thisApprover) < 0) {
            for (int i = 0; i < allApproverIdList.size(); i++) {
                if (approvedUserIds.indexOf(allApproverIdList.get(i)) >= 0) {
                    thisApprover = allApproverIdList.get(i);
                }
            }
        }

        log.debug("找到的所有审批人是：" + CommonUtil.contactListStrings(allApproverIdList));
        allApproverIdList = allApproverIdList.stream().distinct().collect(Collectors.toList());
        log.debug("thisApprover找到的上一个已审批人：" + thisApprover);

        //如果是月度考核评价，转正评价流程，且当前处理人为空，说明是来初始化流程第一环节的处理人，取allApproverIdList第一个人即可；
        if (StringUtils.isEmpty(thisApprover) &&
                (flowCode.equals(BusiEnumDefine.flowCodeMonthlyCheck)
                    || flowCode.equals(BusiEnumDefine.flowCodeTurnFormalCheck))) {
            for (int i = 0; i < allApproverIdList.size(); i++) {
                String approverId = allApproverIdList.get(i);
                if(!StringUtils.isEmpty(approverId)){
                    log.debug("初始化月度/转正评价流程时，找到了第一个配置的审批人：" + approverId);
                    return approverId;
                }
            }
        }

        for (int i = 0; i < allApproverIdList.size(); i++) {
            String approverId = allApproverIdList.get(i);
            if (approverId.equals(thisApprover)) {
                if ((i + 1) < allApproverIdList.size()) {
                    log.debug("找到了：" + allApproverIdList.get(i + 1));
                    // 获取下一个考核人信息
                    return allApproverIdList.get(i + 1);
                } else {
                    //当前审批人为最后一个考核人工号，返回 ""
                    log.debug("没找到，返回空");
                    return "";
                }
            }
        }
        if (workerId.equals(thisApprover)) {
            log.debug("是员工在提交；");
            //当前审批人等于被审批人， 返回第一个考核人
            return approverIdList.get(0);

        }
        log.debug("已经审批过，需要关闭；");
        //都已经审批过，返回 ""
        return "";
    }

    //回退流程到上个状态 ,承诺,计划直接回退到员工,其他不会退
    public Boolean backSpecificFlowInst(TbWorkerDTO workerDTO) {
        String workerId = workerDTO.getWorkerId();
        String flowId = workerDTO.getFlowId();

        TbFlowInst flowInst = tbFlowInstMapper.selectById(flowId);
        if (flowInst != null) {
            TbFlowInstDTO flowInstDTO = JSONObject.parseObject(JSONObject.toJSONString(flowInst), TbFlowInstDTO.class);

            Integer flowStatus = flowInstDTO.getFlowStatus();

            TbFlowInstDTO toFlowInstDTO = new TbFlowInstDTO();
            BeanUtils.copyProperties(flowInstDTO, toFlowInstDTO);


            if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromiseExamine) {
                toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromise);
                toFlowInstDTO.setApprovalUserIds(workerId);
            } else if (flowStatus == BusiEnumDefine.flowStatusTurnFormalExamine) {
                toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalPlan);
                toFlowInstDTO.setApprovalUserIds(workerId);
            }

            //审批人清除
            toFlowInstDTO.setApprovedUserIds("");
            updateSpecificFlowInst(workerDTO, flowInstDTO, toFlowInstDTO);
            //具体业务去处理审批记录，这里不再处理

            //更新待办
            todoTaskService.initOrUpdateTodoTask(toFlowInstDTO);
            //发邮件 待处理人发送邮件
            sendMail(toFlowInstDTO);

        } else {
            throw new AppBusinessException("未找到您的流程信息，请联系管理员处理");
        }

        return true;
    }


//    //回退流程到上个状态
//    public Boolean backSpecificFlowInst(TbWorkerDTO workerDTO) {
//        String workerId = workerDTO.getWorkerId();
//        String flowId = workerDTO.getFlowId();
//
////        TbFlowInst flowInst = new TbFlowInst();
////        flowInst.setWorkerId(workerId);
////        flowInst.setFlowId(flowId);
//        TbFlowInst flowInst = tbFlowInstMapper.selectById(flowId);
//        if (flowInst != null) {
//            TbFlowInstDTO flowInstDTO = JSONObject.parseObject(JSONObject.toJSONString(flowInst), TbFlowInstDTO.class);
//
//
//            String lastApprovalId = getLastApproverId(workerDTO, flowInstDTO);
//            Integer flowStatus = flowInstDTO.getFlowStatus();
//
//            TbFlowInstDTO toFlowInstDTO = new TbFlowInstDTO();
//            BeanUtils.copyProperties(flowInstDTO, toFlowInstDTO);
//
//
//            if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromise || flowStatus == BusiEnumDefine.flowStatusTurnFormalPlan) {
//
//
//            } else if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromiseExamine) {
//                if (StringUtils.isEmpty(lastApprovalId)) {
//                    toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromise);
//                    toFlowInstDTO.setApprovalUserIds(workerId);
//                } else {
//                    toFlowInstDTO.setApprovalUserIds(lastApprovalId);
//                }
//
//            } else if (flowStatus == BusiEnumDefine.flowStatusTurnFormalExamine) {
//                if (StringUtils.isEmpty(lastApprovalId)) {
//                    toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalPlan);
//                    toFlowInstDTO.setApprovalUserIds(workerId);
//                } else {
//                    toFlowInstDTO.setApprovalUserIds(lastApprovalId);
//                }
//
//            } else if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromiseCheck) {
//                toFlowInstDTO.setApprovalUserIds(lastApprovalId);
//
//            } else if (flowStatus == BusiEnumDefine.flowStatusMonthlyPromiseCheck || flowStatus == BusiEnumDefine.flowStatusTurnFormalCheck) {
//                toFlowInstDTO.setApprovalUserIds(lastApprovalId);
//            }
//
//            //审批人清除
//            String approvedUserIds = toFlowInstDTO.getApprovedUserIds();
//            int index = approvedUserIds.indexOf(lastApprovalId);
//            if (index > -1) {
//                String target = approvedUserIds.substring(index);
//                approvedUserIds.replaceAll(target, lastApprovalId).replaceAll(",,", ",");
//            }
//            toFlowInstDTO.setApprovedUserIds(lastApprovalId);
//            updateSpecificFlowInst(workerDTO, flowInstDTO, toFlowInstDTO);
//            //具体业务去处理审批记录，这里不再处理
//            //发邮件 待处理人发送邮件
//            sendMail(toFlowInstDTO);
//            //更新待办
//            todoTaskService.initOrUpdateTodoTask(toFlowInstDTO);
//        } else {
//            throw new AppBusinessException("未找到您的流程信息，请联系管理员处理");
//        }
//
//        return true;
//    }


    /**
     * 获取上一个审批人工号
     * 当前审批人为空， 返回最后一个不为空的考核人工号
     * 当前审批人为第一个个考核人工号，返回 ""
     * 其他获取上一个不为空考核人工号
     * todo
     */
    public String getLastApproverId(TbWorkerDTO workerDTO, TbFlowInstDTO flowInstDTO) {

        String firstApprover = workerDTO.getFirstApprover();
        String secondApprover = workerDTO.getSecondApprover();
        String thirdApprover = workerDTO.getThirdApprover();
        String finalApprover = workerDTO.getFinalApprover();
        String finalJudger = workerDTO.getFinalJudger();
        String approvedUserIds = flowInstDTO.getApprovedUserIds();

        String firstApproverId = StringUtils.isEmpty(firstApprover) ? "" : firstApprover.split("/")[1];
        String secondApproverId = StringUtils.isEmpty(secondApprover) ? "" : secondApprover.split("/")[1];
        String thirdApproverId = StringUtils.isEmpty(thirdApprover) ? "" : thirdApprover.split("/")[1];
        String finalApproverId = StringUtils.isEmpty(finalApprover) ? "" : finalApprover.split("/")[1];
        String finalJudgerId = StringUtils.isEmpty(finalJudger) ? "" : finalJudger.split("/")[1];

        String approvalUserIds = flowInstDTO.getApprovalUserIds();

        //审批过的考核人
        List<String> approvedIdList = new ArrayList<>();
        if (!StringUtils.isEmpty(firstApproverId) && !StringUtils.isEmpty(approvedUserIds) && approvedUserIds.indexOf(firstApproverId) > -1) {
            approvedIdList.add(firstApproverId);
        }
        if (!StringUtils.isEmpty(secondApproverId) && !StringUtils.isEmpty(approvedUserIds) && approvedUserIds.indexOf(secondApproverId) > -1) {
            approvedIdList.add(secondApproverId);
        }
        if (!StringUtils.isEmpty(thirdApproverId) && !StringUtils.isEmpty(approvedUserIds) && approvedUserIds.indexOf(thirdApproverId) > -1) {
            approvedIdList.add(thirdApproverId);
        }
        if (!StringUtils.isEmpty(finalApproverId) && !StringUtils.isEmpty(approvedUserIds) && approvedUserIds.indexOf(finalApproverId) > -1) {
            approvedIdList.add(finalApproverId);
        }
        if (!StringUtils.isEmpty(finalJudgerId) && !StringUtils.isEmpty(approvedUserIds) && approvedUserIds.indexOf(finalJudgerId) > -1) {
            approvedIdList.add(finalJudgerId);
        }
        int size = approvedIdList.size();
        if (size > 0) {
            return approvedIdList.get(size - 1);
        }

        return "";
    }


    /**
     * 转办
     *
     * @param flowInstDTOS
     */

    @Override
    public void transferSpecificFlowInst(List<TbFlowInstDTO> flowInstDTOS) {

        String approverId = flowInstDTOS.get(0).getApprovalUserIdsTransfer();
        if (StringUtils.isEmpty(approverId)) {
            throw new AppBusinessException("转办的目标员工不能为空，请检查后再试");
        }

//        List<String> flowIds = flowInstDTOS.stream().map(TbFlowInstDTO::getFlowId).collect(Collectors.toList());
//        QueryWrapper<TbFlowInst> queryWrapper = new QueryWrapper<>();
//        queryWrapper.in(flowIds.size() > 0, "flow_id", flowIds);
//        List<TbFlowInst> tbFlowInsts = tbFlowInstMapper.selectList(queryWrapper);
//        flowInstDTOS = JSONObject.parseArray(JSON.toJSONString(tbFlowInsts), TbFlowInstDTO.class);
        List<String> workerIds = flowInstDTOS.stream().map(TbFlowInstDTO::getWorkerId).collect(Collectors.toList());

        QueryWrapper<TbWorker> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(workerIds.size() > 0, "worker_id", workerIds);
        List<TbWorker> tbWorkers = tbWorkerMapper.selectList(queryWrapper);
        Map<String, TbWorker> workerMap = tbWorkers.stream().collect(Collectors.toMap(o -> o.getWorkerId(), o -> o));

        flowInstDTOS.forEach(tbFlowInstDTO -> {
            String oriApprovalUserIds = tbFlowInstDTO.getApprovalUserIds();
            StringBuilder allApprovals = new StringBuilder();
            TbWorker tbWorker = workerMap.get(tbFlowInstDTO.getWorkerId());
            StringBuilder approvedUserIds = new StringBuilder();
            if (!StringUtils.isEmpty(tbFlowInstDTO.getApprovedUserIds())) {
                approvedUserIds.append(tbFlowInstDTO.getApprovedUserIds());
            }
            String worker = tbFlowInstDTO.getWorkerName() + "/" + tbFlowInstDTO.getWorkerId();
            if (BusiEnumDefine.flowStatusMonthlyPromise == tbFlowInstDTO.getFlowStatus()) {
                throw new AppBusinessException(worker + "在填写月度承诺阶段，不允许转办");
            }
            if (BusiEnumDefine.flowStatusLittleTaskDoing == tbFlowInstDTO.getFlowStatus()) {
                throw new AppBusinessException(worker + "填写小任务诺阶段，不允许转办");
            }
            if (BusiEnumDefine.flowStatusTurnFormalPlan == tbFlowInstDTO.getFlowStatus()) {
                throw new AppBusinessException(worker + "在填写转正计划阶段，不允许转办");
            }
            if (!StringUtils.isEmpty(approvedUserIds.toString()) && approvedUserIds.toString().indexOf(approverId) >= 0) {
                throw new AppBusinessException(worker + "不能转办给已审批的考核人");
            }
            if (approverId.equals(oriApprovalUserIds)) {
                throw new AppBusinessException(worker + "不能转办给当前考核人");
            }
            if (approverId.equals(tbFlowInstDTO.getWorkerId())) {
                throw new AppBusinessException(worker + "不能转办给新员工");
            }
            if (tbWorker != null&&BusiEnumDefine.flowStatusLittleTaskExamine != tbFlowInstDTO.getFlowStatus()) {
                if (!StringUtils.isEmpty(tbWorker.getFirstApprover()) && tbWorker.getFirstApprover().indexOf(approverId) >= 0) {
                    throw new AppBusinessException(worker + "不能转办给第一考核人");
                }
                if (!StringUtils.isEmpty(tbWorker.getSecondApprover()) && tbWorker.getSecondApprover().indexOf(approverId) >= 0) {
                    throw new AppBusinessException(worker + "不能转办给第二考核人");
                }
                if (!StringUtils.isEmpty(tbWorker.getThirdApprover()) && tbWorker.getThirdApprover().indexOf(approverId) >= 0) {
                    throw new AppBusinessException(worker + "不能转办给第三考核人");
                }
                if (!StringUtils.isEmpty(tbWorker.getFinalApprover()) && tbWorker.getFinalApprover().indexOf(approverId) >= 0) {
                    throw new AppBusinessException(worker + "不能转办给最终考核人");
                }
                if (!StringUtils.isEmpty(tbWorker.getFinalJudger()) && tbWorker.getFinalJudger().indexOf(approverId) >= 0) {
                    throw new AppBusinessException(worker + "不能转办给最终决策人");
                }
            }


            approvedUserIds.append(oriApprovalUserIds + ",");
            tbFlowInstDTO.setApprovalUserIds(approverId);
            tbFlowInstDTO.setApprovedUserIds(approvedUserIds.toString());
            updateFlowInst(tbFlowInstDTO);

            String opinion = "";
            if (!StringUtils.isEmpty(tbFlowInstDTO.getOpinion())) {
                opinion = tbFlowInstDTO.getOpinion();
            }
            setApprovalRecord(tbFlowInstDTO, BusiEnumDefine.APPROVAL_TYPE_TRANSFER,
                    tbFlowInstDTO.getWorkerId() + "的流程从" + oriApprovalUserIds + "转办至" + approverId + " " + opinion);

            //更新待办
            todoTaskService.initOrUpdateTodoTask(tbFlowInstDTO);
            //发邮件 待处理人发送邮件
            sendMail(tbFlowInstDTO);
        });

    }

    @Override
    public void endSpecificFlowInst(List<TbFlowInstDTO> flowInstDTOS) {

        String opinion = flowInstDTOS.get(0).getOpinion();
        /**
         *  关闭待办， 更改状态， 清空正在审批人
         */
        flowInstDTOS.forEach(tbFlowInstDTO -> {
            tbFlowInstDTO.setApprovalUserIds("");
            tbFlowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTermination);
            tbFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTermination);
            updateFlowInst(tbFlowInstDTO);
            setApprovalRecord(tbFlowInstDTO, BusiEnumDefine.APPROVAL_TYPE_TERMINAL, opinion);
            //更新待办：关闭待办
            todoTaskService.initOrUpdateTodoTask(tbFlowInstDTO);
        });
    }

    @Override
    @Transactional
    public void mailReminder(List<TbFlowInstDTO> flowInstDTOS) {

        List<String> flowIds = flowInstDTOS.stream().map(o -> o.getFlowId()).collect(Collectors.toList());
        List<SdTodoTask> todoTasks = todoTaskService.getBaseMapper().selectList(new QueryWrapper<SdTodoTask>().in("docunid", flowIds));
        Map<String, String> urlMap = todoTasks.stream().collect(Collectors.toMap(o -> o.getDocunid(), o -> StringUtils.isEmpty(o.getTodopcurl())? o.getUrl():o.getTodopcurl()));

        flowInstDTOS.forEach(tbFlowInstDTO -> {
            String pcUrl = urlMap.get(tbFlowInstDTO.getFlowId());
            sendMailFun(tbFlowInstDTO, pcUrl);

        });
    }


    public void sendMail(TbFlowInstDTO flowInstDTO) {

        List<SdTodoTask> todoTasks = todoTaskService.getBaseMapper().selectList(new QueryWrapper<SdTodoTask>().eq("docunid", flowInstDTO.getFlowId()));
        String pcUrl = todoTasks.size() > 0 ? todoTasks.get(0).getTodopcurl() : "";
        if(StringUtils.isEmpty(pcUrl)&&todoTasks.size()>0){
            pcUrl = todoTasks.get(0).getUrl();
        }
        sendMailFun(flowInstDTO, pcUrl);
    }


    public void sendMailFun(TbFlowInstDTO flowInstDTO, String pcUrl) {

        String workerId = flowInstDTO.getWorkerId();
        String workerName = flowInstDTO.getWorkerName();

        Integer flowStatus = flowInstDTO.getFlowStatus();
        StringBuilder emailCode = new StringBuilder();
        if (BusiEnumDefine.flowStatusMonthlyPromise == flowStatus) {
            emailCode.append(BusiEnumDefine.EMAIL_CODE_FILL_MONTHLY_PROMISE);
        } else if (BusiEnumDefine.flowStatusMonthlyPromiseExamine == flowStatus) {
            emailCode.append(BusiEnumDefine.EMAIL_CODE_FILL_MONTHLY_PROMISE_EXAMINE);
        } else if (BusiEnumDefine.flowStatusMonthlyPromiseCheck == flowStatus) {
            emailCode.append(BusiEnumDefine.EMAIL_CODE_FILL_MONTHLY_PROMISE_CHECK);
        } else if (BusiEnumDefine.flowStatusTurnFormalPlan == flowStatus) {
            emailCode.append(BusiEnumDefine.EMAIL_CODE_FILL_TURN_FORMAL_PLAN);
        } else if (BusiEnumDefine.flowStatusTurnFormalExamine == flowStatus) {
            emailCode.append(BusiEnumDefine.EMAIL_CODE_FILL_TURN_FORMAL_EXAMINE);
        } else if (BusiEnumDefine.flowStatusTurnFormalCheck == flowStatus) {
            emailCode.append(BusiEnumDefine.EMAIL_CODE_FILL_TURN_FORMAL_CHECK);
        }else if(BusiEnumDefine.flowStatusLittleTaskDoing == flowStatus){
            emailCode.append(BusiEnumDefine.TASK_FINISH_SUBMIT);
        }

        SdAllWorker allWorker = commService.getAllWorkerDoFromLocalCache(flowInstDTO.getApprovalUserIds());
        SdEmailTemplate emailTemplate = emailTemplateService.getById(emailCode.toString());
        String content = emailTemplate.getEmailTemplateContent().replace("{新员工姓名/工号}", workerName + "/" + workerId)
                .replace("{员工姓名/工号}", allWorker.getWorkerName() + "/" + allWorker.getWorkerId())
                .replace("{N}", "一") + "<br>" + (pcUrl == null ? "" : "<p><a href=\"" + pcUrl + "\" target=\"_blank\">点此进入</a></p>");

        String noticeTitle = emailTemplate.getEmailTemplateTitle();

        SdNoticeRecord sdNoticeRecord = new SdNoticeRecord();
        sdNoticeRecord.setNoticeId(IdWorker.nextId() + "");
        sdNoticeRecord.setFlowId(flowInstDTO.getFlowId());
        sdNoticeRecord.setApplyUserId(workerId);
        sdNoticeRecord.setNoticeType(BusiEnumDefine.NOTICE_TYPE_EMAIL);
        sdNoticeRecord.setTargetId(allWorker.getWorkerId());
        sdNoticeRecord.setTargetName(allWorker.getWorkerName());
        sdNoticeRecord.setTargetEmail(allWorker.getEmail());
        sdNoticeRecord.setNoticeTitle(noticeTitle);
        sdNoticeRecord.setNoticeContent(content);
        sdNoticeRecord.setCreateTime(new Date());
        commService.sendMessage(sdNoticeRecord);
    }


    //流程控制
    @Override
    @Transactional
    public void controlSpecificFlowInst(List<TbFlowInstDTO> flowInstDTOS) {
        List<String> workerIds = flowInstDTOS.stream().map(TbFlowInstDTO::getWorkerId).collect(Collectors.toList());
        List<TbWorker> tbWorkers = tbWorkerMapper.selectBatchIds(workerIds);
        List<TbWorkerDTO> tbWorkerDTOS = JSONArray.parseArray(JSON.toJSONString(tbWorkers), TbWorkerDTO.class);
        Map<String, TbWorkerDTO> tbWorkerDTOMap = tbWorkerDTOS.stream().collect(Collectors.toMap(o -> o.getWorkerId(), o -> o));


        flowInstDTOS.forEach(tbFlowInstDTO -> {
            TbWorkerDTO tbWorkerDTO = tbWorkerDTOMap.get(tbFlowInstDTO.getWorkerId());
            if (tbWorkerDTO != null) {

                TbFlowInstDTO toFlowInstDTO = new TbFlowInstDTO();
                BeanUtils.copyProperties(tbFlowInstDTO, toFlowInstDTO);

                String approvalName = toFlowInstDTO.getApprovalName();
                if (StringUtils.isEmpty(approvalName)) {
                    throw new AppBusinessException("请选择控制流程的目标状态");
                }
                Integer reApprovalFlag = toFlowInstDTO.getReApprovalFlag();

                String firstApprover = tbWorkerDTO.getFirstApprover();
                String secondApprover = tbWorkerDTO.getSecondApprover();
                String thirdApprover = tbWorkerDTO.getThirdApprover();
                String finalApprover = tbWorkerDTO.getFinalApprover();
                String finalJudger = tbWorkerDTO.getFinalJudger();

                String firstApproverId = StringUtils.isEmpty(firstApprover) ? "" : firstApprover.split("/")[1];
                String secondApproverId = StringUtils.isEmpty(secondApprover) ? "" : secondApprover.split("/")[1];
                String thirdApproverId = StringUtils.isEmpty(thirdApprover) ? "" : thirdApprover.split("/")[1];
                String finalApproverId = StringUtils.isEmpty(finalApprover) ? "" : finalApprover.split("/")[1];
                String finalJudgerId = StringUtils.isEmpty(finalJudger) ? "" : finalJudger.split("/")[1];


                if ("转正计划填写".equals(approvalName)) {
                    toFlowInstDTO.setApprovalUserIds(tbWorkerDTO.getWorkerId());
                    toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalPlan);
                } else if ("月度承诺填写".equals(approvalName)) {
                    toFlowInstDTO.setApprovalUserIds(tbWorkerDTO.getWorkerId());
                    toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromise);
                } else {
                    StringBuilder approvalId = new StringBuilder();
                    if ("第一考核人".equals(approvalName)) {
                        approvalId.replace(0, approvalId.length(), firstApproverId);
                    } else if ("第二考核人".equals(approvalName)) {
                        approvalId.replace(0, approvalId.length(), secondApproverId);
                    } else if ("第三考核人".equals(approvalName)) {
                        approvalId.replace(0, approvalId.length(), thirdApproverId);
                    } else if ("最终考核人".equals(approvalName)) {
                        approvalId.replace(0, approvalId.length(), finalApproverId);
                    } else if ("最终决策人".equals(approvalName)) {
                        approvalId.replace(0, approvalId.length(), finalJudgerId);
                    }
                    toFlowInstDTO.setApprovalUserIds(approvalId.toString());
                    if (toFlowInstDTO.getFlowCode().equals(BusiEnumDefine.flowCodeMonthlyPromise)) {
                        toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromiseExamine);
                    } else if (toFlowInstDTO.getFlowCode().equals(BusiEnumDefine.flowCodeTurnFormalPlan)) {
                        toFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalExamine);
                    }
                }
                //流程控制的目标id
                String approvalUserIds = toFlowInstDTO.getApprovalUserIds();
                //1是, 2否
                if (reApprovalFlag == 1) {
                    String approvedUserIds = toFlowInstDTO.getApprovedUserIds();
                    int index = approvedUserIds.indexOf(approvalUserIds);
                    if (index > -1) {
                        String target = approvedUserIds.substring(index);
                        approvedUserIds.replaceAll(target, approvalUserIds);
                    }
                    toFlowInstDTO.setApprovedUserIds("");
                }

                //更新流程并给目标流程设值
                updateSpecificFlowInst(tbWorkerDTO, tbFlowInstDTO, toFlowInstDTO);
                setApprovalRecord(toFlowInstDTO, BusiEnumDefine.APPROVAL_TYPE_FLOW_CONTROL,
                        tbFlowInstDTO.getWorkerName() + "/" + tbFlowInstDTO.getWorkerId() + "的流程由" + tbFlowInstDTO.getApprovalUserIds() + "控制到" + approvalUserIds);

                //更新待办
                todoTaskService.initOrUpdateTodoTask(toFlowInstDTO);
                //发邮件 待处理人发送邮件
                sendMail(toFlowInstDTO);

            } else {
                throw new AppBusinessException("未找到员工" + tbFlowInstDTO.getWorkerName() + "/" + tbFlowInstDTO.getWorkerId() + "的信息，请检查后再试");
            }
        });

    }

    /**
     * 流程控制 及 审批人变更
     */
    public Boolean updateSpecificFlowInst(TbWorkerDTO workerDTO, TbFlowInstDTO fromFlowInstDTO, TbFlowInstDTO toFlowInstDTO) {
        log.info(" updateSpecificFlowInst workerDTO: " + workerDTO);
        log.info(" updateSpecificFlowInst fromFlowInstDTO: " + fromFlowInstDTO);
        log.info(" updateSpecificFlowInst toFlowInstDTO: " + toFlowInstDTO);
        Integer fromFlowStatus = fromFlowInstDTO.getFlowStatus();
        String fromFlowCode = fromFlowInstDTO.getFlowCode();
        String toFlowCode = toFlowInstDTO.getFlowCode();
        Integer toFlowStatus = toFlowInstDTO.getFlowStatus();
        String toApprovalUserIds = toFlowInstDTO.getApprovalUserIds();

        Date joinDate = workerDTO.getJoinDate();
        int probationMonth = workerDTO.getProbationMonth();
        String workerId = workerDTO.getWorkerId();
        String workerName = workerDTO.getWorkerName();
        String firstApprover = workerDTO.getFirstApprover();
        String finalJudger = workerDTO.getFinalApprover();

        TbFlowInstDTO flowInstDTO = new TbFlowInstDTO();
        BeanUtils.copyProperties(toFlowInstDTO, flowInstDTO);
//        flowInstDTO.setApprovedUserIds("");
        flowInstDTO.setArriveTime(new Date());
        String approvalUserId = StringUtils.isEmpty(toApprovalUserIds) ? firstApprover : toApprovalUserIds;

        if (BusiEnumDefine.flowCodeMonthlyPromise.equals(toFlowCode)) {
            if (toFlowStatus == BusiEnumDefine.flowStatusMonthlyPromise) {
                flowInstDTO.setApprovalUserIds(workerId);
                flowInstDTO.setFlowStatus(toFlowStatus);
                flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageMonthlyPromise);
            } else if (toFlowStatus == BusiEnumDefine.flowStatusMonthlyPromiseExamine) {
                flowInstDTO.setApprovalUserIds(approvalUserId);
                flowInstDTO.setFlowStatus(toFlowStatus);
                flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageMonthlyPromiseExamine);
            }
        } else if (BusiEnumDefine.flowCodeMonthlyCheck.equals(toFlowCode)) {
            flowInstDTO.setApprovalUserIds(approvalUserId);
        } else if (BusiEnumDefine.flowCodeTurnFormalPlan.equals(toFlowCode)) {
            if (toFlowStatus == BusiEnumDefine.flowStatusTurnFormalPlan) {
                flowInstDTO.setApprovalUserIds(workerId);
                flowInstDTO.setFlowStatus(toFlowStatus);
                flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTurnFormalPlan);
            } else if (toFlowStatus == BusiEnumDefine.flowStatusTurnFormalExamine) {
                flowInstDTO.setApprovalUserIds(approvalUserId);
                flowInstDTO.setFlowStatus(toFlowStatus);
                flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTurnFormalExamine);
            }
        } else if (BusiEnumDefine.flowCodeTurnFormalCheck.equals(toFlowCode)) {
            flowInstDTO.setApprovalUserIds(approvalUserId);
        }

        if (toFlowStatus == BusiEnumDefine.flowStatusFinished) {
            flowInstDTO.setApprovalUserIds("");
            flowInstDTO.setFlowStatus(toFlowStatus);
            flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageFinished);
        }

        updateFlowInst(flowInstDTO);

        return true;
    }

    //审批记录
    public Boolean setApprovalRecord(TbFlowInstDTO flowInstDTO, Integer approvalType, String approvalNote) {

        TbApprovalRecord tbApprovalRecord = new TbApprovalRecord();
        tbApprovalRecord.setApprovalId(IdWorker.nextId() + "");
        tbApprovalRecord.setFlowId(flowInstDTO.getFlowId());
        tbApprovalRecord.setFlowArriveTime(flowInstDTO.getArriveTime());
        tbApprovalRecord.setApprovalType(approvalType);
        tbApprovalRecord.setApprovalUserId(commService.getLoginUserId());
        tbApprovalRecord.setApprovalUserInfo(commService.getLoginUserIdAndName());
        tbApprovalRecord.setApprovalTime(new Date());
        tbApprovalRecord.setApprovalNote(approvalNote);

        tbApprovalRecordMapper.insert(tbApprovalRecord);

        return true;
    }

/*    public static void main(String[] args) throws ParseException {
        TbFlowInstServiceImpl tbFlowInstService = new TbFlowInstServiceImpl();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date date =sdf.parse("2022-02-15");
        System.out.println(tbFlowInstService.getDaysToEnd(date));
        System.out.println(tbFlowInstService.getDaysAll(date));

    }*/

    /**
     * 根据员工信息生成流程信息 (正常未过期)
     *
     * @param workerDTO 员工信息
     * @return 流程信息 tbFlowInstDTO
     */
    @Override
    public TbFlowInstDTO setSpecificFlowInst(TbWorkerDTO workerDTO) {

        Date joinDate = workerDTO.getJoinDate();
        int probationMonth = workerDTO.getProbationMonth() - 1;
        String workerId = workerDTO.getWorkerId();
        String workerName = workerDTO.getWorkerName();
        String firstApprover = workerDTO.getFirstApprover();
        String finalJudger = workerDTO.getFinalApprover();
        Integer directDeptId = workerDTO.getDirectDeptId();
        Integer flowStage = workerDTO.getFlowStage();

        TbFlowInstDTO flowInstDTO = new TbFlowInstDTO();
        flowInstDTO.setWorkerId(workerId);
        flowInstDTO.setWorkerName(workerName);
        flowInstDTO.setWorkerDeptId(directDeptId);

        int joinMonths = getJoinMonths(joinDate);
        int joinDays = getDaysToEnd(joinDate);
        int dayAll = getDaysAll(joinDate);

        if (flowStage != null && flowStage >= BusiEnumDefine.FLOW_STAGE_MONTHLY_PROMISE_FIRST) {
            if (joinMonths < probationMonth) {

                // 第一个月手动新建，这里跳过
                if (joinDays <= DAY_7 && joinDays > DAY_0 && joinMonths != 0 && flowStage % 2 == 0) {
                    //开始月度承诺填写流程
                    flowInstDTO.setApprovalUserIds(workerId);
                    flowInstDTO.setFlowCode(BusiEnumDefine.flowCodeMonthlyPromise);
                    flowInstDTO.setFlowName("第" + (joinMonths + 1) + "次" + BusiEnumDefine.flowNameMonthlyPromise);
                    flowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromise);
                    flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageMonthlyPromise);
                    workerDTO.setFlowStage((joinMonths + 1) * 10 + 1);
                } else if (dayAll-joinDays <= DAY_7 && flowStage % 2 == 1) {
                    //开始月度考核流程
                    flowInstDTO.setFlowCode(BusiEnumDefine.flowCodeMonthlyCheck);
                    flowInstDTO.setFlowName("第" + (joinMonths + 1) + "次" + BusiEnumDefine.flowNameMonthlyCheck);
                    flowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromiseCheck);
                    flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageMonthlyPromiseCheck);
                    String approvalUserId = getNextApproverId(workerDTO, flowInstDTO, "");
                    flowInstDTO.setApprovalUserIds(approvalUserId);
                    workerDTO.setFlowStage((joinMonths + 1) * 10 + 2);
                }

            } else if (joinMonths == probationMonth) {
                //>=:若最后一个月领导在计划转正日期前没通过转正，会接着创建转正计划审核流程；
                //=:不再创建
                if (joinDays <= DAY_14 && joinDays > DAY_0 && flowStage % 2 == 0) {
                    //转正计划填写流程
                    flowInstDTO.setApprovalUserIds(workerId);
                    flowInstDTO.setFlowCode(BusiEnumDefine.flowCodeTurnFormalPlan);
                    flowInstDTO.setFlowName(BusiEnumDefine.flowNameTurnFormalPlan);
                    flowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalPlan);
                    flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTurnFormalPlan);
                    workerDTO.setFlowStage((joinMonths + 1) * 10 + 1);
                } else if (joinDays > DAY_14 && flowStage % 2 == 1) {
                    //转正计划评价流程
                    flowInstDTO.setFlowCode(BusiEnumDefine.flowCodeTurnFormalCheck);
                    flowInstDTO.setFlowName(BusiEnumDefine.flowNameTurnFormalCheck);
                    flowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalCheck);
                    flowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTurnFormalCheck);
                    String approvalUserId = getNextApproverId(workerDTO, flowInstDTO, "");
                    flowInstDTO.setApprovalUserIds(approvalUserId);
                    workerDTO.setFlowStage((joinMonths + 1) * 10 + 2);
                }
            }
        }
        return flowInstDTO;
    }

    @Override
    @Transactional
    public Integer approvalTask(TbApprovalRecordDTO tbApprovalRecordDTO) {
        Integer approvalType = tbApprovalRecordDTO.getSubmitType();
        int result = 0;
        String loginUserId = tbApprovalRecordDTO.getApprovalUserId();
        String idAndName = tbApprovalRecordDTO.getApprovalUserInfo();
        Date now = new Date();

        if (approvalType == BusiEnumDefine.APPROVAL_APPROVE || approvalType == BusiEnumDefine.APPROVAL_BACKUP) {
            String flowId = tbApprovalRecordDTO.getFlowId();
            TbFlowInst tbFlowInst = tbFlowInstMapper.selectById(flowId);

            //记录审核记录
            TbApprovalRecord approvalRecord = JSONObject.parseObject(JSON.toJSONString(tbApprovalRecordDTO), TbApprovalRecord.class);
            approvalRecord.setApprovalId(IdWorker.nextId() + "");
            approvalRecord.setFlowArriveTime(tbFlowInst.getArriveTime());
            approvalRecord.setApprovalType(BusiEnumDefine.FLOW_STATUS_CHECK_TASK);
            approvalRecord.setApprovalUserId(loginUserId);
            approvalRecord.setApprovalUserInfo(idAndName);
            approvalRecord.setApprovalTime(now);
            approvalRecord.setApprovalResult(approvalType);
            approvalRecord.setApproveChannel(BusiEnumDefine.APPROVE_CHANNEL_PC);
            tbApprovalRecordMapper.insert(approvalRecord);

            //修改inst状态
            if (approvalType == BusiEnumDefine.APPROVAL_BACKUP) {
                tbFlowInst.setFlowStatus(BusiEnumDefine.FLOW_STATUS_EXECUTE_TASK);
                tbFlowInst.setCurrentStage(BusiEnumDefine.currentStageLittleTaskDoing);
            } else {
                tbFlowInst.setFlowStatus(BusiEnumDefine.FLOW_STATUS_FINISH);
                tbFlowInst.setCurrentStage(BusiEnumDefine.currentStageFinished);
            }
            tbFlowInst.setArriveTime(now);
            tbFlowInst.setFinishTime(now);
            String approvedUserIds = tbFlowInst.getApprovedUserIds();
            //历史处理人为空，或者历史处理人不包含当前员工，准备插入数据
            if (StringUtils.isEmpty(approvedUserIds) || !approvedUserIds.contains(tbFlowInst.getApprovalUserIds())) {
                //初始人
                String basicUser = StringUtils.isEmpty(approvedUserIds) ? "" : approvedUserIds + ",";
                tbFlowInst.setApprovedUserIds(basicUser + tbFlowInst.getApprovalUserIds());
            }
            tbFlowInst.setApprovalUserIds("");
            result += tbFlowInstMapper.updateById(tbFlowInst);

            //发邮件 退回后给员工发送邮件
            if (approvalType == BusiEnumDefine.APPROVAL_BACKUP) {
                SdEmailTemplate taskEmail = sdEmailTemplateMapper.selectById(BusiEnumDefine.APPROVAL_BACKUP_TASK);
                SdAllWorker allWorker = commService.getAllWorkerDoFromLocalCache(tbFlowInst.getWorkerId());
                sendEmail(allWorker, flowId, loginUserId, taskEmail);
            }

            //待办
            todoTaskService.initOrUpdateTodoTask(tbFlowInst);
        } else if (approvalType == BusiEnumDefine.APPROVAL_TRANSFER) {
            String flowId = tbApprovalRecordDTO.getFlowId();
            TbFlowInst tbFlowInst = tbFlowInstMapper.selectById(flowId);

            //记录审核记录
            TbApprovalRecord approvalRecord = JSONObject.parseObject(JSON.toJSONString(tbApprovalRecordDTO), TbApprovalRecord.class);
            approvalRecord.setApprovalId(IdWorker.nextId() + "");
            approvalRecord.setFlowArriveTime(tbFlowInst.getArriveTime());
            approvalRecord.setApprovalType(92); //转办
            approvalRecord.setApprovalUserId(loginUserId);
            approvalRecord.setApprovalUserInfo(idAndName);
            approvalRecord.setApproveChannel(BusiEnumDefine.APPROVE_CHANNEL_PC);
            approvalRecord.setApprovalTime(now);
            tbApprovalRecordMapper.insert(approvalRecord);

            //修改inst状态
            tbFlowInst.setArriveTime(now);
            String approvedUserIds = tbFlowInst.getApprovedUserIds();
            if (StringUtils.isEmpty(approvedUserIds) || !approvedUserIds.contains(tbFlowInst.getApprovalUserIds())) {
                tbFlowInst.setApprovedUserIds(approvedUserIds + "," + tbFlowInst.getApprovalUserIds());
            }
            tbFlowInst.setApprovalUserIds(tbApprovalRecordDTO.getTransferWorker());
            result += tbFlowInstMapper.updateById(tbFlowInst);

            SdEmailTemplate taskEmail = sdEmailTemplateMapper.selectById(BusiEnumDefine.NEW_TASK_EMAIL);

            //发邮件 给转办对象
            SdAllWorker allWorker = commService.getAllWorkerDoFromLocalCache(tbApprovalRecordDTO.getTransferWorker());
            sendEmail(allWorker, flowId, loginUserId, taskEmail);

            //待办
            todoTaskService.initOrUpdateTodoTask(tbFlowInst);
        }
        return result;
    }

    @Override
    public void taskFormSubmit(ConfigTheFormSubmit formSubmit) {
        JSONObject data = JSONObject.parseObject(StringUtils.isEmpty(formSubmit.getData()) ? "" : formSubmit.getData());

        TbApprovalRecordDTO tbApprovalRecordDTO = new TbApprovalRecordDTO();
        String empNumber = formSubmit.getEmpNumber();
        QueryWrapper<SdAllWorker> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SdAllWorker::getDomainAccount, empNumber);
        List<SdAllWorker> sdAllWorkers = sdAllWorkerMapper.selectList(queryWrapper);
        if (!sdAllWorkers.isEmpty()) {
            SdAllWorker worker = sdAllWorkers.get(0);
            tbApprovalRecordDTO.setApprovalUserId(worker.getWorkerId());
            tbApprovalRecordDTO.setApprovalUserInfo(worker.getWorkerId() + "/" + worker.getWorkerName());
        }
        tbApprovalRecordDTO.setFlowId(formSubmit.getDocId());
        if ("Agree".equals(formSubmit.getButtonType())) {
            String approvalNote = data.getString("approvalNote");
            String approvalScore = data.getString("approvalScore");
            if (StringUtils.isEmpty(approvalNote) || StringUtils.isEmpty(approvalScore)) {
                throw new BusinessException(StatusCodeEnum.UNKNOW_ERROR.getCode(), "请填写审批说明和审批评分");
            }
            tbApprovalRecordDTO.setApprovalScore(approvalScore);
            tbApprovalRecordDTO.setApprovalNote(approvalNote);
            tbApprovalRecordDTO.setSubmitType(BusiEnumDefine.APPROVAL_APPROVE);
        } else if ("Reject".equals(formSubmit.getButtonType())) {
            String approvalNote = data.getString("approvalNote");
            if (StringUtils.isEmpty(approvalNote)) {
                throw new BusinessException(StatusCodeEnum.UNKNOW_ERROR.getCode(), "请填写审批说明");
            }
            tbApprovalRecordDTO.setApprovalNote(approvalNote);
            tbApprovalRecordDTO.setSubmitType(BusiEnumDefine.APPROVAL_BACKUP);
        } else {
            tbApprovalRecordDTO.setSubmitType(BusiEnumDefine.APPROVAL_TRANSFER);
            //转办人
            QueryWrapper<SdAllWorker> targetQW = new QueryWrapper<>();
            targetQW.lambda().eq(SdAllWorker::getDomainAccount, formSubmit.getTargetReceiver());
            List<SdAllWorker> allWorkers = sdAllWorkerMapper.selectList(targetQW);
            if (!allWorkers.isEmpty()) {
                SdAllWorker worker = allWorkers.get(0);
                tbApprovalRecordDTO.setTransferWorker(worker.getWorkerId());
                tbApprovalRecordDTO.setApprovalNote(formSubmit.getOpinion());
            }
        }
        approvalTask(tbApprovalRecordDTO);
    }

    //一次性创建所有过期流程

    /**
     * 根据员工信息 一次性创建所有 过期 流程
     *
     * @param workerDTO
     * @return tbFlowInstDTO 流程信息列表
     */
    @Override
    public ArrayList<TbFlowInstDTO> createAllExpireSpecificFlowInst(TbWorkerDTO workerDTO,Set<String> flowWorkerIdCodeSet) {
        Date joinDate = workerDTO.getJoinDate();

        int joinMonths = getJoinMonths(joinDate);
        int joinDays = getDaysToEnd(joinDate);

        int probationMonth = workerDTO.getProbationMonth() - 1;
        String workerId = workerDTO.getWorkerId();
        String workerName = workerDTO.getWorkerName();
        Integer directDeptId = workerDTO.getDirectDeptId();
        String firstApprover = workerDTO.getFirstApprover();
        String finalJudger = workerDTO.getFinalApprover();
        Integer flowStage = workerDTO.getFlowStage();


        ArrayList<TbFlowInstDTO> tbFlowInstDTOS = new ArrayList<>();

//        if (flowStage != null && flowStage == BusiEnumDefine.FLOW_STAGE_MONTHLY_PROMISE_FIRST) {

            for (int i = 0; i < joinMonths + 1; i++) {
                TbFlowInstDTO fillFlowInstDTO = new TbFlowInstDTO();
                TbFlowInstDTO checkFlowInstDTO = new TbFlowInstDTO();

                fillFlowInstDTO.setWorkerId(workerId);
                fillFlowInstDTO.setWorkerName(workerName);
                fillFlowInstDTO.setWorkerDeptId(directDeptId);
                checkFlowInstDTO.setWorkerId(workerId);
                checkFlowInstDTO.setWorkerName(workerName);
                checkFlowInstDTO.setWorkerDeptId(directDeptId);

                //月度考核
                if (i < probationMonth) {
                    // 第一个月手动新建，这里跳过
                    //如果入职时间比最后一月度考核小于7，则未过期，不在这里新建
                    if (i != 0 && (i != joinMonths || joinDays > DAY_7)) {
                        //开始月度承诺填写流程
                        checkFlowInstDTO.setApprovalUserIds(workerId);
                        checkFlowInstDTO.setFlowCode(BusiEnumDefine.flowCodeMonthlyPromise);
                        checkFlowInstDTO.setFlowName("第" + (i + 1) + "次" + BusiEnumDefine.flowNameMonthlyPromise);
                        checkFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromise);
                        checkFlowInstDTO.setCurrentStage(BusiEnumDefine.currentStageMonthlyPromise);
                        log.debug("转正计划评价 obj:" + checkFlowInstDTO.toString());
                        if (flowWorkerIdCodeSet.contains(workerId + checkFlowInstDTO.getFlowCode() + checkFlowInstDTO.getFlowName())) {
                            continue;
                        }
                        tbFlowInstDTOS.add(checkFlowInstDTO);
                        workerDTO.setFlowStage((i + 1) * 10 + 1);

                    }
                    //最后一个月度考核未过期，则跳过
                    if (i != joinMonths) {
                        //开始月度考核流程,
                        fillFlowInstDTO.setFlowCode(BusiEnumDefine.flowCodeMonthlyCheck);
                        fillFlowInstDTO.setFlowName("第" + (i + 1) + "次" + BusiEnumDefine.flowNameMonthlyCheck);
                        fillFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusMonthlyPromiseCheck);
                        fillFlowInstDTO.setCurrentStage(BusiEnumDefine.currentStageMonthlyPromiseCheck);
                        String approvalUserId = getNextApproverId(workerDTO, fillFlowInstDTO, "");
                        fillFlowInstDTO.setApprovalUserIds(approvalUserId);
                        log.debug("月度考核 obj:" + fillFlowInstDTO.toString());
                        if (flowWorkerIdCodeSet.contains(workerId + fillFlowInstDTO.getFlowCode() + fillFlowInstDTO.getFlowName())) {
                            continue;
                        }
                        tbFlowInstDTOS.add(fillFlowInstDTO);
                        workerDTO.setFlowStage((i + 1) * 10 + 2);
                    }

                }

                //转正计划
                if (i == probationMonth) {

                    //如果入职时间比转正计划时间小于14，则未过期，不在这里新建
                    if ((i != joinMonths || joinDays > DAY_14)) {
                        //转正计划填写流程
                        fillFlowInstDTO.setApprovalUserIds(workerId);
                        fillFlowInstDTO.setFlowCode(BusiEnumDefine.flowCodeTurnFormalPlan);
                        fillFlowInstDTO.setFlowName(BusiEnumDefine.flowNameTurnFormalPlan);
                        fillFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalPlan);
                        fillFlowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTurnFormalPlan);
                        log.debug("转正计划填写 obj:" + fillFlowInstDTO.toString());
                        if (flowWorkerIdCodeSet.contains(workerId + BusiEnumDefine.flowCodeTurnFormalPlan + fillFlowInstDTO.getFlowName())) {
                            continue;
                        }
                        tbFlowInstDTOS.add(fillFlowInstDTO);
                        workerDTO.setFlowStage((i + 1) * 10 + 1);
                    }

                    //转正评价流程未过期，则跳过
                    if (i != joinMonths) {
                        //转正计划评价流程
                        checkFlowInstDTO.setFlowCode(BusiEnumDefine.flowCodeTurnFormalCheck);
                        checkFlowInstDTO.setFlowName(BusiEnumDefine.flowNameTurnFormalCheck);
                        checkFlowInstDTO.setFlowStatus(BusiEnumDefine.flowStatusTurnFormalCheck);
                        checkFlowInstDTO.setCurrentStage(BusiEnumDefine.currentStageTurnFormalCheck);
                        String approvalUserId = getNextApproverId(workerDTO, checkFlowInstDTO, "");
                        checkFlowInstDTO.setApprovalUserIds(approvalUserId);
                        log.debug("转正计划评价 obj:" + checkFlowInstDTO.toString());
                        if (flowWorkerIdCodeSet.contains(workerId + checkFlowInstDTO.getFlowCode() + checkFlowInstDTO.getFlowName())) {
                            continue;
                        }
                        tbFlowInstDTOS.add(checkFlowInstDTO);
                        workerDTO.setFlowStage((i + 1) * 10 + 2);
                    }
                }
            }
//        }

        tbFlowInstDTOS.forEach(obj -> log.debug("final obj=" + obj.toString()));
        return tbFlowInstDTOS;
    }

    /**
     * 根据  获取目的流程信息
     *
     * @param workerDTO
     * @param formFlowInstDTO
     * @param toFlowInstDTO
     * @return 目的流程对象
     */
    public TbFlowInstDTO getSpecificFlowInst(TbWorkerDTO workerDTO, TbFlowInstDTO formFlowInstDTO, TbFlowInstDTO toFlowInstDTO) {

        Date joinDate = workerDTO.getJoinDate();
        int probationMonth = workerDTO.getProbationMonth();
        String workerId = workerDTO.getWorkerId();
        String workerName = workerDTO.getWorkerName();
        String firstApprover = workerDTO.getFirstApprover();
        String finalJudger = workerDTO.getFinalApprover();


        String fromFlowCode = formFlowInstDTO.getFlowCode();
        String fromFlowName = formFlowInstDTO.getFlowName();
        int fromFlowStatus = formFlowInstDTO.getFlowStatus();
        String fromCurrentStage = formFlowInstDTO.getCurrentStage();
        String toFlowCode = formFlowInstDTO.getFlowCode();
        int toFlowStatus = formFlowInstDTO.getFlowStatus();

        if (!StringUtils.isEmpty(fromFlowCode) && fromFlowCode.equals(toFlowCode)) {
            throw new AppBusinessException("只能在同一流程内控制");
        }

        if (BusiEnumDefine.flowCodeMonthlyPromise.equals(fromFlowCode)) {
            if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromise)) {
                toFlowInstDTO.setApprovalUserIds(workerId);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            } else if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromiseExamine)) {
                toFlowInstDTO.setApprovalUserIds(firstApprover);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            }
        } else if (BusiEnumDefine.flowCodeMonthlyCheck.equals(fromFlowCode)) {
            if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromiseCheck)) {
                toFlowInstDTO.setApprovalUserIds(workerId);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            } else if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromiseExamine)) {
                toFlowInstDTO.setApprovalUserIds(firstApprover);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            }
        }
        return formFlowInstDTO;
    }

    //获取 控制流程目标信息
    public Boolean setSpecificFlowInst(TbWorkerDTO workerDTO, TbFlowInstDTO formFlowInstDTO, TbFlowInstDTO toFlowInstDTO) throws Exception {

        Date joinDate = workerDTO.getJoinDate();
        int probationMonth = workerDTO.getProbationMonth();
        String workerId = workerDTO.getWorkerId();
        String workerName = workerDTO.getWorkerName();
        String firstApprover = workerDTO.getFirstApprover();
        String finalJudger = workerDTO.getFinalApprover();


        String fromFlowCode = formFlowInstDTO.getFlowCode();
        String fromFlowName = formFlowInstDTO.getFlowName();
        int fromFlowStatus = formFlowInstDTO.getFlowStatus();
        String fromCurrentStage = formFlowInstDTO.getCurrentStage();
        String toFlowCode = formFlowInstDTO.getFlowCode();
        int toFlowStatus = formFlowInstDTO.getFlowStatus();

        if (!StringUtils.isEmpty(fromFlowCode) && fromFlowCode.equals(toFlowCode)) {
            throw new AppBusinessException("只能在同一流程内控制");
        }

        if (BusiEnumDefine.flowCodeMonthlyPromise.equals(fromFlowCode)) {
            if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromise)) {
                toFlowInstDTO.setApprovalUserIds(workerId);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            } else if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromiseExamine)) {
                toFlowInstDTO.setApprovalUserIds(firstApprover);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            }
        } else if (BusiEnumDefine.flowCodeMonthlyCheck.equals(fromFlowCode)) {
            if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromiseCheck)) {
                toFlowInstDTO.setApprovalUserIds(workerId);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            } else if (toFlowInstDTO.getFlowStatus().equals(BusiEnumDefine.flowStatusMonthlyPromiseExamine)) {
                toFlowInstDTO.setApprovalUserIds(firstApprover);
                toFlowInstDTO.setFlowCode(fromFlowCode);
                toFlowInstDTO.setFlowName(fromFlowName);
            }
        }
        return true;
    }

    /**
     * 计算入职月数 0为入职第1个月 1为入职第2个月 ...
     *
     * @param joinDate
     * @return
     */
    public Integer getJoinMonths(Date joinDate) {
        Calendar rightNow = Calendar.getInstance();
        Calendar joinDateCalendar = Calendar.getInstance();
        joinDateCalendar.setTime(joinDate);

        int joinYear = joinDateCalendar.get(Calendar.YEAR);
        int newYear = rightNow.get(Calendar.YEAR);
        int joinMonth = joinDateCalendar.get(Calendar.MONTH);
        int nowMonth = rightNow.get(Calendar.MONTH);


        if (rightNow.compareTo(joinDateCalendar) == -1) {
            //入职时间大于当前时间
            int months = (joinYear - newYear) * 12 + (joinMonth - nowMonth);
            rightNow.add(Calendar.MONTH, months);
            if (joinDateCalendar.compareTo(rightNow) == -1) {
                months--;
            }
            return -1 - months;
        } else {
            int months = (newYear - joinYear) * 12 + (nowMonth - joinMonth);
            joinDateCalendar.add(Calendar.MONTH, months);
            if (rightNow.compareTo(joinDateCalendar) == -1) {
                months--;
            }
            return months;
        }
    }

//    public static Integer getJoinMonthsTest(Date joinDate) {
//        Calendar rightNow = Calendar.getInstance();
//        Calendar joinDateCalendar = Calendar.getInstance();
//        joinDateCalendar.setTime(joinDate);
//
//        int joinYear = joinDateCalendar.get(Calendar.YEAR);
//        int newYear = rightNow.get(Calendar.YEAR);
//        int joinMonth = joinDateCalendar.get(Calendar.MONTH);
//        int nowMonth = rightNow.get(Calendar.MONTH);
//
//
//        if (rightNow.compareTo(joinDateCalendar) == -1) {
//            //入职时间大于当前时间
//            int months = (joinYear - newYear) * 12 + (joinMonth - nowMonth);
//            rightNow.add(Calendar.MONTH, months);
//            if (joinDateCalendar.compareTo(rightNow) == -1) {
//                months--;
//            }
//            return -1 - months;
//        } else {
//            int months = (newYear - joinYear) * 12 + (nowMonth - joinMonth);
//            joinDateCalendar.add(Calendar.MONTH, months);
//            if (rightNow.compareTo(joinDateCalendar) == -1) {
//                months--;
//            }
//            return months;
//        }
//    }

    /**
     * 计算距离月度考核结束天数（自然日）
     *
     * @param joinDate
     * @return
     */
    public Integer getDaysToEnd(Date joinDate) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.set(Calendar.HOUR, 0);
        Calendar joinDateCalendar = Calendar.getInstance();
        joinDateCalendar.setTime(joinDate);

        int months = getJoinMonths(joinDate);
        joinDateCalendar.add(Calendar.MONTH, months);
        Long joinTime = joinDateCalendar.getTime().getTime();
        Long nowTime = rightNow.getTime().getTime();

        Double days = (nowTime - joinTime) / (1000 * 60 * 60 * 24.0);
        days = Math.ceil(days);


        return days.intValue();
    }

    /**
     * 计算相差流程到达天数
     *
     * @param currentTime
     * @param joinDate
     * @return
     */
    public Integer getDaysToNow(Long currentTime, Long joinDate) {
        //获取到达时间
        //东八区快8个小时，new Date(0) 是 1970-01-01 08:00:00
        Double daysNow = (currentTime + EIGHT_HOUR_TIME) / (1000 * 60 * 60 * 24.0);
        Double daysArrive = (joinDate + EIGHT_HOUR_TIME) / (1000 * 60 * 60 * 24.0);
        Double days = Math.ceil(daysNow) - Math.ceil(daysArrive);
        return days.intValue();
    }

    /**
     * 计算当前周期总天数
     *
     */
    public Integer getDaysAll(Date joinDate) {
        int months = getJoinMonths(joinDate);
        Calendar endData = Calendar.getInstance();
        Calendar begData = Calendar.getInstance();
        Calendar joinDateCalendar = Calendar.getInstance();
        endData.setTime(joinDate);
        begData.setTime(joinDate);
        begData.add(Calendar.MONTH, months);
        endData.add(Calendar.MONTH, months+1);

        Long begTime = begData.getTime().getTime();
        Long endTime = endData.getTime().getTime();

        Double days = (endTime - begTime) / (1000 * 60 * 60 * 24.0);
        days = Math.ceil(days);
        return days.intValue();
    }


//    public static Integer getDaysToEndTest(Date joinDate) {
//        Calendar rightNow = Calendar.getInstance();
//        rightNow.set(Calendar.HOUR, 0);
//        Calendar joinDateCalendar = Calendar.getInstance();
//        joinDateCalendar.setTime(joinDate);
//
//        int months = getJoinMonthsTest(joinDate);
//        joinDateCalendar.add(Calendar.MONTH, months);
//        Long joinTime = joinDateCalendar.getTime().getTime();
//        Long nowTime = rightNow.getTime().getTime();
//
//        Double days = (nowTime - joinTime) / (1000 * 60 * 60 * 24.0);
//        days = Math.ceil(days);
//
//        return days.intValue();
//    }


//    public static void main(String[] args) {
//        Calendar joinDateCalendar = Calendar.getInstance();
//        joinDateCalendar.set(Calendar.HOUR, 12);
//        joinDateCalendar.set(2021, 11, 01);
//
//        System.out.println(joinDateCalendar.get(Calendar.YEAR) + "/" + (joinDateCalendar.get(Calendar.MONTH) + 1) + "/" + joinDateCalendar.get(Calendar.DAY_OF_MONTH));
//        for (int i = 0; i < 100; i++) {
//            joinDateCalendar.add(Calendar.DAY_OF_MONTH, 1);
//            int days = getDaysToEndTest(joinDateCalendar.getTime());
//            System.out.println(i + "  joinDateCalendar" + joinDateCalendar.get(Calendar.YEAR) + "/" + (joinDateCalendar.get(Calendar.MONTH) + 1) + "/" + joinDateCalendar.get(Calendar.DAY_OF_MONTH) +
//                    "     JoinMonths:" + getJoinMonthsTest(joinDateCalendar.getTime()) + "    JoinDays:" + days + "--------------");
//        }
//
////        TbWorkerDTO workerDTO = new TbWorkerDTO();
//////        workerDTO.setFirstApprover("123/123");
////        workerDTO.setSecondApprover("456/456");
////        workerDTO.setThirdApprover("789/789");
////        workerDTO.setFinalApprover("000/000");
////        workerDTO.setFinalJudger("111/111");
////        TbFlowInstDTO flowInstDTO = new TbFlowInstDTO();
//////        flowInstDTO.setApprovedUserIds("456;789");
////        String thisApprover = "";
//////        String nextId = getNextApproverIdTest(workerDTO, flowInstDTO, thisApprover);
//////        System.out.println("nextId:" + nextId);
//    }


    @Override
    public void initTodoTask(TbFlowInst tbFlowInst) {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String approvalUserIds = tbFlowInst.getApprovalUserIds();
        String accounts = "";
        String names = "";
        if (!StringUtils.isEmpty(approvalUserIds)) {
            SdAllWorker sdAllWorker = commService.getAllWorkerDoFromLocalCache(approvalUserIds); //通过当前处理人查出当前处理人AllWorker
            accounts = sdAllWorker.getDomainAccount();
            names = sdAllWorker.getWorkerName();
        }

        String status = tbFlowInst.getFlowStatus() == BusiEnumDefine.FLOW_STATUS_FINISH ? BusiEnumDefine.PERFORMANCE_TODO_APPROVED :
                tbFlowInst.getFlowStatus() == BusiEnumDefine.FLOW_STATUS_CHECK_TASK ? BusiEnumDefine.PERFORMANCE_TODO_APPROVING :
                        BusiEnumDefine.PERFORMANCE_TODO_WAITING;

        String processId = "TASK_FLOW";
        String systemId = "HR_NEM";
        Integer orderStatus = tbFlowInst.getFlowStatus();
        SdTodoTask one = todoTaskService.getOne(new QueryWrapper<SdTodoTask>()
                .eq("systemid", systemId)
                .eq("processid", processId)
                .eq("docunid", tbFlowInst.getFlowId()));
        TodoTaskNodeEnum orderStatusEnum = TodoTaskNodeEnum.getEnumByValue(orderStatus);
        String acceptType = BusiEnumDefine.TODO_ACCEPT_PC;

        SdTodoTask task = new SdTodoTask();
        task.setSystemid(systemId);
        task.setSubject("新员工小任务");
        task.setAccepttype(acceptType);
        task.setAdduserid(tbFlowInst.getWorkerId());
        task.setAddusername(tbFlowInst.getWorkerName());
        task.setAppid(null);
        task.setApplytime(sf.format(tbFlowInst.getCreateTime()));
        task.setAssigner("");
        task.setStatus(status);
        task.setAuthorid(accounts);
        task.setAuthorname(names);
        StringBuilder url = new StringBuilder();
        url.append(todoPcUrl);
        String[] nodeIds = {"MONTH_WORK_PROMISE", "MONTH_PROMISE_APPROVAL", "MONTH_PROMISE_APPROVAL"};
        if (Arrays.asList(nodeIds).contains(orderStatusEnum.toString())) {
            url.append("person/index/");
        }
        task.setUrl(url.toString());
        task.setTimestamp(sf.format(tbFlowInst.getArriveTime()));
        task.setMaildaily(null);
        task.setNodename(orderStatusEnum.getName());
        task.setNodeid(orderStatusEnum.toString());
        task.setProcessid(processId);
        task.setProcessname("");
        task.setRedirecturl("");
        task.setIsbatch("0"); //能否批量处理（1是\0否）
        task.setDocunid(tbFlowInst.getFlowId());
        if (one == null) {
            task.setEnduserid("");
            todoTaskService.save(task);
        } else {
            String enduserid = one.getEnduserid();
            if (!enduserid.contains(tbFlowInst.getApprovalUserIds())) {
                String userId = "";
                if (!StringUtils.isEmpty(enduserid)) {
                    userId = enduserid + ",";
                }
                task.setEnduserid(userId + tbFlowInst.getApprovalUserIds());
            }
            todoTaskService.update(task, new UpdateWrapper<SdTodoTask>()
                    .eq("systemid", systemId)
                    .eq("processid", processId)
                    .eq("docunid", tbFlowInst.getFlowId()));
        }
        todoTaskService.sendTodoTask(task);
    }


    /**
     * @title: initFuzzyExample
     * @description: 初始化 模糊查询 example
     * @params: [ dto ]
     * @return: tk.mybatis.mapper.entity.Example
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    private Example initFuzzyExample(TbFlowInstDTO dto) {
        Example example = InitExampleOrderByUtils.initExampleOrderBy(TbFlowInst.class, dto.getOrderBy());
        Example.Criteria criteriaName = example.createCriteria();
        if (null != dto) {
            if (null != dto.getFlowId() && !"".equals(dto.getFlowId())) {
                criteriaName.andLike("FlowId", "%" + dto.getFlowId() + "%");
            }
            if (null != dto.getFlowCode() && !"".equals(dto.getFlowCode())) {
                criteriaName.andLike("FlowCode", "%" + dto.getFlowCode() + "%");
            }
            if (null != dto.getFlowName() && !"".equals(dto.getFlowName())) {
                criteriaName.andLike("FlowName", "%" + dto.getFlowName() + "%");
            }
            if (null != dto.getWorkerId() && !"".equals(dto.getWorkerId())) {
                criteriaName.andLike("WorkerId", "%" + dto.getWorkerId() + "%");
            }
            if (null != dto.getWorkerName() && !"".equals(dto.getWorkerName())) {
                criteriaName.andLike("WorkerName", "%" + dto.getWorkerName() + "%");
            }
            if (null != dto.getWorkerDeptId() && !"".equals(dto.getWorkerDeptId())) {
                criteriaName.andLike("WorkerDeptId", "%" + dto.getWorkerDeptId() + "%");
            }
            if (null != dto.getFlowStatus() && !"".equals(dto.getFlowStatus())) {
                criteriaName.andLike("FlowStatus", "%" + dto.getFlowStatus() + "%");
            }
            if (null != dto.getCurrentStage() && !"".equals(dto.getCurrentStage())) {
                criteriaName.andLike("CurrentStage", "%" + dto.getCurrentStage() + "%");
            }
            if (null != dto.getCreateTime() && !"".equals(dto.getCreateTime())) {
                criteriaName.andLike("CreateTime", "%" + dto.getCreateTime() + "%");
            }
            if (null != dto.getArriveTime() && !"".equals(dto.getArriveTime())) {
                criteriaName.andLike("ArriveTime", "%" + dto.getArriveTime() + "%");
            }
            if (null != dto.getFinishTime() && !"".equals(dto.getFinishTime())) {
                criteriaName.andLike("FinishTime", "%" + dto.getFinishTime() + "%");
            }
            if (null != dto.getApprovalUserIds() && !"".equals(dto.getApprovalUserIds())) {
                criteriaName.andLike("ApprovalUserIds", "%" + dto.getApprovalUserIds() + "%");
            }
            if (null != dto.getApprovedUserIds() && !"".equals(dto.getApprovedUserIds())) {
                criteriaName.andLike("ApprovedUserIds", "%" + dto.getApprovedUserIds() + "%");
            }
            if (null != dto.getFlowNote() && !"".equals(dto.getFlowNote())) {
                criteriaName.andLike("FlowNote", "%" + dto.getFlowNote() + "%");
            }
        }
        return example;
    }

    /**
     * @title: initExample
     * @description: 初始化 精确查询 example
     * @params: [ dto ]
     * @return: tk.mybatis.mapper.entity.Example
     * @createTime: 2022-01-19
     * @version: 1.0
     * @author: l22886
     */
    private Example initExample(TbFlowInstDTO dto) {
        Example example = InitExampleOrderByUtils.initExampleOrderBy(TbFlowInst.class, dto.getOrderBy());
        Example.Criteria criteriaName = example.createCriteria();
        if (null != dto) {
            if (null != dto.getFlowId() && !"".equals(dto.getFlowId())) {
                criteriaName.andEqualTo("FlowId", dto.getFlowId());
            }
            if (null != dto.getFlowCode() && !"".equals(dto.getFlowCode())) {
                criteriaName.andEqualTo("FlowCode", dto.getFlowCode());
            }
            if (null != dto.getFlowName() && !"".equals(dto.getFlowName())) {
                criteriaName.andEqualTo("FlowName", dto.getFlowName());
            }
            if (null != dto.getWorkerId() && !"".equals(dto.getWorkerId())) {
                criteriaName.andEqualTo("WorkerId", dto.getWorkerId());
            }
            if (null != dto.getWorkerName() && !"".equals(dto.getWorkerName())) {
                criteriaName.andEqualTo("WorkerName", dto.getWorkerName());
            }
            if (null != dto.getWorkerDeptId() && !"".equals(dto.getWorkerDeptId())) {
                criteriaName.andEqualTo("WorkerDeptId", dto.getWorkerDeptId());
            }
            if (null != dto.getFlowStatus() && !"".equals(dto.getFlowStatus())) {
                criteriaName.andEqualTo("FlowStatus", dto.getFlowStatus());
            }
            if (null != dto.getCurrentStage() && !"".equals(dto.getCurrentStage())) {
                criteriaName.andEqualTo("CurrentStage", dto.getCurrentStage());
            }
            if (null != dto.getCreateTime() && !"".equals(dto.getCreateTime())) {
                criteriaName.andEqualTo("CreateTime", dto.getCreateTime());
            }
            if (null != dto.getArriveTime() && !"".equals(dto.getArriveTime())) {
                criteriaName.andEqualTo("ArriveTime", dto.getArriveTime());
            }
            if (null != dto.getFinishTime() && !"".equals(dto.getFinishTime())) {
                criteriaName.andEqualTo("FinishTime", dto.getFinishTime());
            }
            if (null != dto.getApprovalUserIds() && !"".equals(dto.getApprovalUserIds())) {
                criteriaName.andEqualTo("ApprovalUserIds", dto.getApprovalUserIds());
            }
            if (null != dto.getApprovedUserIds() && !"".equals(dto.getApprovedUserIds())) {
                criteriaName.andEqualTo("ApprovedUserIds", dto.getApprovedUserIds());
            }
            if (null != dto.getFlowNote() && !"".equals(dto.getFlowNote())) {
                criteriaName.andEqualTo("FlowNote", dto.getFlowNote());
            }
        }
        return example;
    }


}
